C++17 if init for the while loop? - c++

For some home work I'm doing the following:
int main() {
ofstream file("log.txt");
file << setw(5) << "i"
<< setw(15) << "h"
<< setw(15) << "n"
<< setw(15) << "sum"
<< setw(15) << "diff"
<< endl;
auto write2file = [&file](int i, double h, double n, double sum, double diff) {
file << setw(5) << i
<< setw(15) << h
<< setw(15) << n
<< setw(15) << sum
<< setw(15) << diff
<< endl;
};
double a = 0;
double b = 2;
int n = 1;
double h = (b-a)/n;
double sum = sum_analytic;
double diff = 1;
while (diff > pow(10, -4)) {
h = (b-a)/++n;
sum = ntgrt(a, b, n, h);
diff = abs(sum - sum_analytic);
static int i = 0;
write2file(++i, h, n, sum, diff);
}
}
Considering the C++17 if init feature (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r1.html) I'm kind of seing the same pattern here when I declare h, sum and diff outside the while loop but they are used only inside.
Is there a better way to write it, may be taking advantage of C++17 features?

Then what you want is a for loop:
for(double diff = 1; diff > pow(10, -4);)
{
double h = (b-a)/++n;
double sum = ntgrt(a, b, n, h);
diff = abs(sum - sum_analytic);
....
}
There was no point in adding this capability to while since you can just use for and leave off the increment statement.

I'd start with some C++98 features to reduce repetition.
template <class I, class F>
void write2file(std::ostream &os, I i, F h, I n, F sum, F diff) {
using std::setw;
os << setw(5) << i
<< setw(15) << h
<< setw(15) << n
<< setw(15) << sum
<< setw(15) << diff
<< "\n";
}
// ...
write2file(file, "i", "h", "n", "sum", "diff");
// ...
write2file(file, ++i, h, n, sum, diff);
It would appear that when they're used, i and n always have the same value. I'd just use one of the two rather than both.
Your pow(10, -4) would probably be better off as 1e-4.
I think some good use of C++98 can probably clean up the loop as well. I'd move it into a function template, something on this general order:
template <typename F>
void show_convergence(double a, double b, F f, double sum_a, std::ostream &os) {
double diff = 1.0;
for (int n=1; diff > 1e-4; n++) {
double h = (b-a)/n;
double sum = f(a, b, n, h);
diff = abs(sum-sum_a);
write2file(os, n, h, sum, diff);
}
}
Technically, this wouldn't have to be a template--but it's fairly harmless, and avoids the ugliness of a pointer to a function (which can also lead to a fair degree of inefficiency). Then you'd call this something like this:
show_convergence(0, 2, ntgrt, sum_analytic, file);

Related

What would be a more efficient way of storing variables?

I am working on a music program that calls notes from the chromatic scale based on intervals. These interval variables (h - half step, w - whole step and wh -whole and a half step) will be used for determining scale incriments (Major = WWHWWWH) and will later be used to measure interval lengths across a vector of strings to potentially output measurements like "3 Whole Steps and a Half Step".
I'm wondering what would be the more efficient way to store the simple variables, as I would eventually like to make a cellphone app out of it and want it to be as easy on the battery/memory as possible. . And I am still learning. Here are my thoughts:
int H = 1;
int W = 2;
int WH = 3;
Int Fiv = 5;
Int Sev = 7;
or
int H = 1;
int W = H+H;
int WH = W + H;
int Fiv = WH+W;
int Sev = Fiv + W;
Int H = 1; int W = H*2; int WH = W+H; etc..
I'm primarily interested in how the differentiation of initialization will effect both memory and performance if at all?
I know I shouldn't have everything in main, but this is a work in progress, and I am obviously new to programming - so please look past the layout .. here is the code it's presently being used in..
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include <sstream>
#include <vector>
#include <map>
const std::vector<std::string> st_sharps{"C","C#","D","D#","E","F","F#","G","G#","A","A#","B" };
const std::vector<std::string> st_flats{"C","Db","D","Eb","E","F","Gb","G","Ab","A","Bb","B" };
struct steps{ int maj = 0; int min = 0;} step;
constexpr int H = 1;
constexpr int W = 2;
constexpr int Tre = 3;
constexpr int Fif = 5;
constexpr int Sev = 7;
const int size = st_flats.size();
const std::vector<int> Major = { W, W, H, W, W, W, H };
struct circle{
std::stringstream sharp;
std::stringstream flat;
std::stringstream minor;
std::stringstream dimin; };
struct scales{
circle fifths;
std::stringstream maj;
std::stringstream min; } scale;
int main(){
//Circle of Fifths
for (int j = 0; j < size; j++){
int five = j * Sev;
scale.fifths.sharp << st_sharps[five % size] << " ";
scale.fifths.flat << st_flats[five % size] << " ";
scale.fifths.minor << st_sharps[((size - Tre) + five) % size] << " ";
scale.fifths.dimin << st_sharps[((size - H) + five) % size] << " ";
}
std::cout << "Circle of Fifths:\n";
std::cout << "Major >> Relative Minor >> Diminished " << std::endl;
std::cout << "Maj: " << scale.fifths.sharp.str() << std::endl;
std::cout << "Min: " << scale.fifths.minor.str() << std::endl;
std::cout << "Dim: " << scale.fifths.dimin.str() << std::endl;
std::cout << "\nflats: " << scale.fifths.flat.str() << "\n" << std::endl;
//Major and Minor Scales
for (int i = 0; i < Major.size(); i++) {
scale.maj << st_sharps[step.maj] << " ";
scale.min << st_flats[((size - Tre) + step.min) % size] << " ";
step.maj += Major[i];
step.min += Major[(i + Fif) % Major.size()];
}
std::cout << "C Major:\n" << scale.maj.str() << "\n" << std::endl;
std::cout << "A Minor:\n" << scale.min.str() << "\n" << std::endl;
return 0;
}
I'd choose a version that expresses "'W' is the double of 'H'" the best way. My preferred way would therefore be:
constexpr int H = 1;
constexpr int W = 2*H;
constexpr int WH = W+H;
Note that your version int W = H++ is not what you probably intend, since H++ is not equal to H+1; it is actually equal to int W = H; H = H + 1.

Don't print variable if it's zero

double a, b, c, d, x, y;
char operation
cout << setw(6) << a << b
<< setw(3) << operation
<< setw(6) << c << d
<< " = "
<< setw(6) << x << y
<< endl;
I'm making a calculator which takes two complex numbers and adds subtracts etc. My question is how do I format my output so that 0's are not displayed.
I.E. if the input is (a+bi)(c+di) the output is a+bi * c+di = x+yi But a, b, c, d, x, y are only displayed if they are nonzero.
I know I can do it with if statements and stuff but I was hoping there's a shorter, more efficient, path.
I don't think you can avoid doing the condition and printing if non-zero somewhere.
About all you can do is wrap it up so most code doesn't need to deal with it:
class complex {
double x;
double i;
public:
// ...
friend std::ostream &operator<<(std::ostream &os, complex const &c) {
// if both parts are 0, we probably want to print *something*
if (c.x == 0.0 && c.i == 0.0)
return os << 0;
if (c.x != 0.0)
os << c.x;
if (c.i != 0.0)
os << c.i << "i";
return os;
}
};
complex a, b, c;
// ...
cout << a << operation << b << " = " c << "\n";
You'll have to add a little more if you want this to honor (for example) width/precision correctly (though for real use, you undoubtedly want to use the complex class that's already in the standard library instead).
Yes, you can do it by including <complex>
std::complex<double> com_one; // value 0 + 0i
std::complex<double> com_two(3.14); // value 3.14 + 0i
std::complex<double> com_three(1.5, 3.14) // value 1.5 + 3.14i
std::complex<double> com_four(com_two); // value is also 3.14 + 0i
Then to use arithmetic operations, you can just use
std::cout << com_one + com_two << std::endl;
std::cout << com_one - 3.14 << std::endl;
std::cout << 2.75 * com_two << std::endl;
com_one += com_three / 2.0;
Source: http://stdcxx.apache.org/doc/stdlibug/20-2.html
For checking if it's a zero check it using if, and compare it with a zero. This is the most clean technique.

C++ Simple calculation outputting 0.0000000000000000 instead of 0.003333

The calculation for dx and dy is returning 0 and I don't see what the issue is. The console seems to show all the correct values are being used.
void drawBackground()
{
double r, g, b, dx, dy, Wx, Wy, Wz;
Ray ray;
cout << "xmax: " << sceneDescription::imagePlaneXmax << " xmin: " << sceneDescription::imagePlaneXmin << endl;
cout << "ymax: " << sceneDescription::imagePlaneYmax << " ymin: " << sceneDescription::imagePlaneYmin << endl;
cout << "Iw: " << sceneDescription::Iw << " Ih: " << sceneDescription::Ih << endl;
cout << " " << endl;
dx = (sceneDescription::imagePlaneXmax - (sceneDescription::imagePlaneXmin))/sceneDescription::Iw;
dy = (sceneDescription::imagePlaneYmax - (sceneDescription::imagePlaneYmin))/sceneDescription::Ih;
std::cout << "dx: "<< boost::format("%1$.16f") % dx << " dy: "<< boost::format("%1$.16f") % dy << endl;
}
sceneDescription.h
#include <glm/glm.hpp>
using namespace glm;
class sceneDescription{
public:
static const int imagePlaneXmin = -1;
static const int imagePlaneXmax = 1;
static const int imagePlaneYmin = -1;
static const int imagePlaneYmax = 1;
static const int Iw = 600;
static const int Ih = 800;
};
Console output:
xmax: 1 xmin: -1
ymax: 1 ymin: -1
Iw: 600 Ih: 800
dx: 0.0000000000000000 dy: 0.0000000000000000
The problem is that the statement:
dx = (sceneDescription::imagePlaneXmax -
(sceneDescription::imagePlaneXmin))/sceneDescription::Iw;
will give the following result:
(1-(-1))/600 = 2/600 = 0.00 (since this is integer division).
You may want to cast the number to double.
Something like this would work:
dx = (double)(sceneDescription::imagePlaneXmax -
(sceneDescription::imagePlaneXmin)) / sceneDescription::Iw;
Since cast operator has higher priority than division, the numerator will be cast by (double) and the denominator will be cast implicitly giving the double result.
Hope that helps!

creating full range of random floats using std::random

I'm attempting to test a mathematical class I've created using random numbers from the full range of representable positivefloats, but I find that I seem to be having a problem with my use of std::random. This program
#include <random>
#include <iostream>
#include <functional>
template <typename T>
class Rand {
public:
Rand(T lo=std::numeric_limits<T>::min(),
T hi=std::numeric_limits<T>::max()) :
r(bind(std::uniform_real_distribution<>(lo, hi),std::mt19937_64{})) {}
T operator()() const { return r(); }
private:
std::function<T()> r;
};
int main()
{
Rand<float> f{};
const int samples = 1000000;
float min = std::numeric_limits<float>::max();
float max = std::numeric_limits<float>::min();
std::cout << "range min = " << max
<< ", max = " << min << '\n';
for (int i=0; i < samples; ++i) {
float r = f();
if (r < min) min = r;
if (r > max) max = r;
}
std::cout << "for n = " << samples
<< "\nsample min = " << min
<< ", max = " << max << std::endl;
}
produces this output
range min = 1.17549e-38, max = 3.40282e+38
for n = 1000000
sample min = 8.14884e+31, max = 3.40281e+38
Clearly the range is extremely skewed toward larger numbers. How do I generate the desired range of floats with a uniform distribution?
In addition to the statistics you have printed out, I've computed both the theoretical and actual mean, variance, skew and kurtosis of this distribution. Here is my code, and the results:
#include <random>
#include <iostream>
#include <functional>
#include <vector>
#include <numeric>
#include <cmath>
template <typename T>
class Rand {
public:
Rand(T lo=std::numeric_limits<T>::min(),
T hi=std::numeric_limits<T>::max()) :
r(bind(std::uniform_real_distribution<>(lo, hi),std::mt19937_64{})) {}
T operator()() const { return r(); }
private:
std::function<T()> r;
};
template <class T>
inline
T
sqr(T x)
{
return x * x;
}
int main()
{
Rand<float> f{};
const int samples = 1000000;
float min = std::numeric_limits<float>::max();
float max = std::numeric_limits<float>::min();
std::vector<float> u;
std::cout << "range min = " << max
<< ", max = " << min << '\n';
for (int i=0; i < samples; ++i) {
float r = f();
if (r < min) min = r;
if (r > max) max = r;
u.push_back(r);
}
std::cout << "for n = " << samples
<< "\nsample min = " << min
<< ", max = " << max << std::endl;
double mean = std::accumulate(u.begin(), u.end(),
double(0)) / u.size();
double var = 0;
double skew = 0;
double kurtosis = 0;
for (int i = 0; i < u.size(); ++i)
{
double d = (u[i] - mean);
double d2 = sqr(d);
var += d2;
skew += d * d2;
kurtosis += d2 * d2;
}
var /= u.size();
double dev = std::sqrt(var);
skew /= u.size() * dev * var;
kurtosis /= u.size() * var * var;
kurtosis -= 3;
double x_mean = ((double)min + max) / 2;
double x_var = sqr((double)max - min) / 12;
double x_skew = 0;
double x_kurtosis = -6./5;
std::cout << std::scientific << '\n';
std::cout << " expected actual\n";
std::cout << "mean " << x_mean << " " << mean << "\n";
std::cout << "variance " << x_var << " " << var << "\n";
std::cout << "skew " << x_skew << " " << skew << "\n";
std::cout << "kurtosis " << x_kurtosis << " " << kurtosis << "\n";
}
And here are the results:
range min = 1.17549e-38, max = 3.40282e+38
for n = 1000000
sample min = 8.14884e+31, max = 3.40281e+38
expected actual
mean 1.701407e+38 1.700724e+38
variance 9.649275e+75 9.645774e+75
skew 0.000000e+00 7.401975e-04
kurtosis -1.200000e+00 -1.199432e+00
Everything is looking pretty good to me.
The biggest point you are missing is that you are not generating numbers between (-max_value,max_value) , but between ( 0 ,max_value).
There are about pow(10,32) numbers between 0 and 8.14884e+31, but there are about pow(10,37) numbers between 8.14884e+31 and 3.40281e+38. Hence the result is obvious.

How can I separate this into 2 functions

I was wondering if anyone could help me with a more elegant way to code this program that I am writing please. The code I have is bellow, I would like to know if there is a way to separate the part that prints out the totals into a new function. I have tried but I always just get the total is 0, so I must be passing things wrong or something.
void printNumbers(int x, double y, double z, double v, int sum, double sum2,int sum3,int sum4){
while(x != 0){
y = sqrt (x);
z = pow (x,2);
v = pow (x,3);
sum = sum + x;
sum2 = sum2 + y;
sum3 = sum3 + z;
sum4 = sum4 + v;
cout << " " << x << setw(12) << setprecision (4) << y << setw(8) << z << setw(8) << v << endl;
x--;
}
cout << " total is" << sum << setw(12) << sum2 << setw(8)<< sum3 << setw(8) << sum4 << endl;
}
This is what I tried, at the time I only had one total to get, but It still did not work just gave the answer 0:
void printFooters(int sum){
cout << " " << "====================================="<< endl;
cout << "Totals " << sum << endl << endl;
cout << " " << "====================================="<< endl;
}
This is how I was calling it in main():
printFooters(sum);
You need to make the sums into references if you want them to be updated.
void printNumbers(int x, double y, double z, double v, int& sum, double& sum2,int& sum3,int& sum4)
If you don't the sums are passed by value, so you just get a copy of the current value of the sums.
Alternatively you can use pointers to the sums, but that would involve changing the syntax when accessing the sum variables.
You should decide first, what variables are input and what variables should carry output. Try to not use one variable for both input and output, it is often more confusing than valuable.
Only input value is x. Everything else is output values. In way you have used that values, content of values is modified only in local copy inside function printNumbers(). They will get lost on end of function. I expect you want to output computed results from function (however then printNumbers is wrong name for that function).
C and C++ always pass variables to function parameters by value. That means, variable is initialized from parameter, but any changes are done only inside function. At the end of function, copy is discarded and will NOT change anything you passed to it.
If you want output from function, you can use return, or use pointers or references to a variable. I suggest to use references in C++, they are easier to understand and easier to use.
Use references instead of copied variables in function. Then, when you modify that value inside function, it will keep modified value after function return.
void f1(int in, int out)
{
out = in + 1;
}
void f2(int in, int &out)
{
out = in + 1;
}
int o1=-1, o2=-1;
f1(1, o1);
f2(1, o2);
cout << o1 << "," << o2 << endl; // will print -1,2
So declare your function as:
void printNumbers(int x, double &y, double &z, double &v, int &sum, double &sum2,int &sum3,int &sum4);
you can then do:
double y,z;
int sum, sum2, sum3, sum4;
printNumbers(4, y, z, sum, sum2, sum3, sum4);
printFooters(sum);
And this time, it should print whatever printNumbers computed. See http://www.cprogramming.com/tutorial/references.html for a bit more, or use google.
You could batch all those parameters into structs, and separate all the calculations and outputs.
This is probably overkill in your case, and is quite a bit of code, but anyway...
struct Powers
{
double sqroot;
int one;
double square;
double cube;
};
Powers calculatePowers(int x)
{
Powers powers;
powers.sqroot = sqrt(x);
powers.one = x;
powers.square = x * x;
powers.cube = x * x * x;
return powers;
}
struct Sums
{
int sum1;
double sum2;
int sum3;
int sum4;
};
Sums addPowers(Sums sums, Powers powers)
{
sums.sum1 += powers.one;
sums.sum2 += powers.sqroot;
sums.sum3 += powers.square;
sums.sum4 += powers.cube;
return sums;
}
void printPowers(Powers powers)
{
cout << " " << powers.one
<< setw(12) << setprecision (4) << powers.sqroot
<< setw(8) << powers.square
<< setw(8) << powers.cube
<< endl;
}
void printTotals(Sums sums)
{
cout << " total is"
<< sums.sum1
<< setw(12) << sums.sum2
<< setw(8) << sums.sum3
<< setw(8) << sums.sum4
<< endl;
}
void doEverything(int x)
{
Sums sums = {0, 0, 0, 0};
while (x > 0)
{
Powers powers = calculatePowers(x);
printPowers(powers);
sums = addPowers(sums, powers);
x--;
}
printTotals(sums);
}