C++ Question on the pow function - c++

I'm trying to get this expression to work, I'm pretty sure its not the parenthesis because I counted all of them. Perhaps there something I'm doing wrong involving the parameter pow (x,y).
double calculatePeriodicPayment()
{
periodicPaymentcalc = (loan * ((interestRate / yearlyPayment))) / (1-((pow ((1+(interestRate / yearlyPayment)))),(-(yearlyPayment * numOfYearLoan))));
return periodicPaymentcalc;
}

Notice how much easier it is to figure out what the function is doing if you break each step up into pieces:
(I find it even easier if your variables match the source material, so I'll name my variables after the ones Wikipedia uses.)
// amortization calculator
// uses annuity formula (http://en.wikipedia.org/wiki/Amortization_calculator)
// A = (P x i) / (1 - pow(1 + i,-n))
// Where:
// A = periodic payment amount
// P = amount of principal
// i = periodic interest rate
// n = total number of payments
double calculatePeriodicPayment()
{
const double P = loan;
const double i = interestRate / yearlyPayment;
const double n = yearlyPayment * numOfYearLoan;
const double A = (P * i) / (1 - pow(1.0 + i, -n));
return A;
}
It's much easier to confirm that the logic of this function does what it should this way.
If you're curious, substituting my variable names in, your parenthises problem is as follows:
const double A = (P * i) / (1 - pow(1 + i)), -n; // <- this is how you have it
const double A = (P * i) / (1 - pow(1 + i, -n)); // <- this is how it should be
With this grouping, you're only passing one argument to pow, which is why the compiler says no overloaded function takes 1 arguments.
Edit: You mentioned I used more variables. However, your compiler will use temporary variables much like I did. Your complex statement will be broken up into pieces, and may look something like this:
double calculatePeriodicPayment()
{
const double temp1 = interestRate / yearlyPayment;
const double temp2 = loan * temp1;
const double temp3 = interestRate / yearlyPayment;
const double temp4 = 1.0 + temp3;
const double temp5 = yearlyPayment * numOfYearLoan;
const double temp6 = -temp5;
const double temp7 = pow(temp4, temp5);
const double temp8 = 1 - temp7;
const double temp9 = temp2 / temp8;
periodicPaymentcalc = temp9;
return periodicPaymentcalc;
}
Mine will also be broken up, and will look like:
double calculatePeriodicPayment()
{
const double P = loan;
const double i = interestRate / yearlyPayment;
const double n = yearlyPayment * numOfYearLoan;
const double temp1 = P * i;
const double temp2 = 1.0 + i;
const double temp3 = -n;
const double temp4 = pow(temp2, temp3);
const double temp5 = 1 - temp4;
const double temp6 = temp1 / temp5;
const double A = temp6;
return A;
}
Perhaps there are some optimizations that the compiler will use, such as noticing that it uses interestRate / yearlyPayment twice in your function, and use the same temporary for both places, but there's no gurantee this will happen. Notice that we use pretty much the same number of variables in both of our functions. I just used more named variables, and fewer unnamed temporaries.

There's a misplaced bracket. Here's a fixed version:
periodicPaymentcalc = (loan * ((interestRate / yearlyPayment))) / (1 - ((pow ((1+(interestRate / yearlyPayment)),(-(yearlyPayment * numOfYearLoan))))));
Use an editor that highlights matching brackets to avoid this kind of errors. Or simply create temporary variables to hold intermediate values.

periodicPaymentcalc = (loan * interestRate / yearlyPayment) /
(1.0 - pow (1.0 + interestRate / yearlyPayment, -yearlyPayment * numOfYearLoan));
Try that. I removed all the redundant parentheses too, as well as changing all literals to doubles, just for good measure.

Related

C Language: Initializing float variable with a calculation

I haven't done a lot of floating point math programming in any language let alone in C.
I'm writing a temperature conversion program as an exercise and have a question about floating point numbers. I have a code frag as listed below. In both cases Temp1 and Temp2 are 0.0 when P_FahrenheitTemp is <> 32.0. However, if I use the CF3 factor in the calculation the LOC VERRKKKS!!! :-)
This seems intuitively obvious to me but... Is this compiler dependent or is a cast operator necessary on the initialization? BTW, I'm writing this code on an IBM iSeries platform using the C/C++ compiler which strictly adheres to ASNI and ISO standards.
Thank you in advance for any info!
Martin Kuester
#define CF3 5/9;
float Conv2Celsius(float P_FahrenheitTemp)
{
float Temp1, Temp2, Temp3;
float ConvAdj = 32.0;
float CF1 = 0.555556;
float CF2 = 5/9;
//[°C] = ([°F] - 32) × 5/9
Temp1 = (P_FahrenheitTemp - ConvAdj) * CF1;
Temp2 = (P_FahrenheitTemp - ConvAdj) * CF2;
Temp3 = (P_FahrenheitTemp - ConvAdj) * CF3;
return(Temperature);
}
Let us look closer.
float CF1 = 0.555556;
Temp1 = (P_FahrenheitTemp - ConvAdj) * CF1;
// same as
Temp1 = (P_FahrenheitTemp - ConvAdj) * (float) 0.555556;
float CF2 = 5/9;
Temp2 = (P_FahrenheitTemp - ConvAdj) * CF2;
// same as
float CF2 = 0; // 5/9 is integer division
Temp2 = (P_FahrenheitTemp - ConvAdj) * 0;
#define CF3 5/9
Temp3 = (P_FahrenheitTemp - ConvAdj) * CF3;
// same as
Temp3 = (P_FahrenheitTemp - ConvAdj) * 5 / 9;
Temp3 = (P_FahrenheitTemp - ConvAdj) * 5.0f / 9;
// ^--- float multiplication -------^
// same as
Temp3 = (P_FahrenheitTemp - ConvAdj) * 5.0f / 9.0f;
// ^--- float divsion ----------------------^
Temp3 "VERRKKKS" because it is not scaling by 5/9. Instead it is a text substitution in the line-of-code and so multiplies by 5 and then divides by 9.
Temp3 is correct and best of the three.
Temp1 is almost correct as not as certainly precise * (float) 0.555556 as * 5.0f/9.0f.
Temp2 is wrong as the answer is always 0, even when it should not be
I have a code frag as listed below. In both cases Temp1 and Temp2 are 0.0 when P_FahrenheitTemp is <> 32.0.
Temp1 is not 0.0.
To set aside the minor additional error in the constant, use at least 9 digits with float and a f suffix.
//float CF1 = 0.555556;
float CF1 = 0.555555556f;
Suggested replacement
float Conv2Celsius(float P_FahrenheitTemp) {
float ConvAdj = 32.0f;
float CF = 5.0f/9.0f; // or 0.555555556f
//[°C] = ([°F] - 32) × 5/9
return (P_FahrenheitTemp - ConvAdj) * CF;
}
In C language the line float CF2 = 5/9; will be processed as follows:
The right side of the assignment operator 5/9 is evaluated first. The compiler here sees two integer values divided on each other so it will save the result into an integer temporary variable. This will lead to truncation of the fractional part of the actual result 0.555556 to 0.
The result will be assigned then to CF2.
What to do?
Alot of options; float CF2 = 5.0/9; or float CF2 = (float)5/9; or even float CF2 = 5./9;
the same with CF3

Representation of Fourier series depends on tabulation points

Well, I had task to create function that does Fourier series with some mathematical function, so I found all the formulas, but the main problem is when I change count of point on some interval to draw those series I have very strange artifact:
This is Fourier series of sin(x) on interavl (-3.14; 314) with 100 point for tabulation
And this is same function with same interval but with 100000 points for tabulation
Code for Fourier series coeficients:
void fourieSeriesDecompose(std::function<double(double)> func, double period, long int iterations, double *&aParams, double *&bParams){
aParams = new double[iterations];
aParams[0] = integrateRiemans(func, 0, period, 1000);
for(int i = 1; i < iterations; i++){
auto sineFunc = [&](double x) -> double { return 2 * (func(x) * cos((2 * x * i * M_PI) / period)); };
aParams[i] = integrateRiemans(sineFunc, -period / 2, period / 2, 1000) / period;
}
bParams = new double[iterations];
for(int i = 1; i < iterations; i++){
auto sineFunc = [&](double x) -> double { return 2 * (func(x) * sin(2 * (x * (i + 1) * M_PI) / period)); };
bParams[i] = integrateRiemans(sineFunc, -period / 2, period / 2, 1000) / period;
}
}
This code I use to reproduce function using found coeficients:
double fourieSeriesCompose(double x, double period, long iterations, double *aParams, double *bParams){
double y = aParams[0];
for(int i = 1; i < iterations; i++){
y += sqrt(aParams[i] * aParams[i] + bParams[i] * bParams[i]) * cos((2 * i * x * M_PI) / period - atan(bParams[i] / aParams[i]));
}
return y;
}
And the runner code
double period = M_PI * 2;
auto startFunc = [](double x) -> double{ return sin(x); };
fourieSeriesDecompose(*startFunc, period, 1000, aCoeficients, bCoeficients);
auto readyFunc = [&](double x) -> double{ return fourieSeriesCompose(x, period, 1000, aCoeficients, bCoeficients); };
tabulateFunc(readyFunc);
scaleFunc();
//Draw methods after this
see:
How to compute Discrete Fourier Transform?
So if I deciphered it correctly the aParams,bParams represent the real and imaginary part of the result then the angles in sin and cos must be the same but you have different! You got this:
auto sineFunc = [&](double x) -> double { return 2*(func(x)*cos((2* x* i *M_PI)/period));
auto sineFunc = [&](double x) -> double { return 2*(func(x)*sin( 2*(x*(i+1)*M_PI)/period));
as you can see its not the same angle. Also what is period? You got iterations! if it is period of the function you want to transform then it should be applied to it and not to the kernel ... Also integrateRiemans does what? its the nested for loop to integrate the furrier transform? Btw. hope that func is real domain otherwise the integration/sumation needs both real and imaginary part not just one ...
So what you should do is:
create (cplx) table of the func(x) data on the interval you want with iterations samples
so for loop where x = x0+i*(x1-x0)/(iterations-1) and x0,x1 is the range you want the func to sample. Lets call it f[i]
for (i=0;i<iteration;i++) f[i]=func(x0+i*(x1-x0)/(iterations-1));
furrier transform it
something like this:
for (i=0;i<iteration;i++) a[i]=b[i]=0;
for (j=0;j<iteration;j++)
for (i=0;i<iteration;i++)
{
a[j]+=f[i]*cos(-2.0*M_PI*i*j/iterations);
b[j]+=f[i]*sin(-2.0*M_PI*i*j/iterations);
}
now a[],b[] should hold your slow DFT result ... beware integer rounding ... depending on compiler you might need to cast some stuff to double to avoid integer rounding.

Iteration causes crash

What is wrong with this iteration?
This particular piece of code is causing my program to crash. When I disable the code it works but of course giving wrong results. It's supposed to compare sigma with sigma_last until they remain equal at e-14.
This is what I tried first:
long double sigma_last = NULL;
do{
if(sigma_last != NULL){
sigma = sigma_last;
}
sigma1 = atan( tan(beta1) / cos(A1) );
sigmaM = (2*sigma1 + sigma) / 2;
d_sigma = B*sin(sigma)*(cos(2*sigmaM)+(1/4)*B*(cos(sigma)
*(-1+2*pow(cos(2*sigmaM),2)))-(1/6)*B*cos(2*sigmaM)
*(-3+4*pow(sin(sigma),2))*(-3+4*pow(cos(2*sigmaM),2)));
sigma_last = sigma + d_sigma;
}
while(set_precision_14(sigma)<= set_precision_14(sigma_last) || set_precision_14(sigma)>= set_precision_14(sigma_last));
Then I tried using a pointer (desperately):
long double *sigma_last;
*sigma_last = NULL;
do{
if(*sigma_last != NULL){
sigma = *sigma_last;
}
sigma1 = atan( tan(beta1) / cos(A1) );
sigmaM = (2*sigma1 + sigma) / 2;
d_sigma = B*sin(sigma)*(cos(2*sigmaM)+(1/4)*B*(cos(sigma)
*(-1+2*pow(cos(2*sigmaM),2)))-(1/6)*B*cos(2*sigmaM)
*(-3+4*pow(sin(sigma),2))*(-3+4*pow(cos(2*sigmaM),2)));
*sigma_last = sigma + d_sigma;
}
while(set_precision_14(sigma)<= set_precision_14(*sigma_last) || set_precision_14(sigma)>= set_precision_14(*sigma_last));
Finding the source of error in entire code and trying to solve it took me hours, cannot really come up with another "maybe this?" . Feel free to smite me.
Here's a github link to my full code if anyone out there's interested.
Your first (and only) iteration, sigma_last will be null, resulting in crash:
*sigma_last = NULL; // <-- dereferencing uninitialized ptr here
if(*sigma_last != NULL) { // <-- dereferencing uninitialized ptr here too
and if that would have been fixed, here:
*sigma_last == sigma + d_sigma;
This is because you have not set sigma_last to point to some valid floating-point space in memory. There doesn't seem to be any point to using a pointer in this particular case, so if I were you, I'd drop it and use a normal long double instead, as in your first attempt.
In your first example you assign NULL, which is really the value zero, to sigma_last. If zero is not what you're intending, you could either go with a value that most certainly will be out of range (say 1e20 and then compare to say < 1e19) or keep a separate boolan for the job. I personally prefer the first option:
long double sigma_last = 1e20;
...
if(sigma_last < 1e19){
sigma = sigma_last;
}
A better way still would be to use an infinite, or finite, loop and then break out at a certain condition. This will make the code easier to read.
Logic
Finally, you seem to have a problem with your logic in the while, since the comparison sigma <= sigma_last || sigma >= sigma_last is always true. It's always smaller, bigger, or equal.
sigma_last does not need to be a pointer. You just need to somehow flag its value to know whether it was already set or not. From your code I am not sure if we can use zero for this purpose, but we can use some constant (long double minimum value), like this one:
#include <float.h>
const long double invalid_constant = LDBL_MIN;
Try this:
long double DESTINATION_CALCULATION_plusplus ( double phi, double lambda, double S, double azimuth,
double a, double b, double *phi2, double* lambda2, double* azimuth2){
phi = phi*M_PI/180;
lambda = lambda*M_PI/180;
double A1;
double eu2 = (pow(a, 2) - pow(b, 2)) / pow(b, 2); //second eccentricity
double c = pow(a,2) / b;
double v = sqrt(1 + (eu2 * pow(cos(phi) , 2)));
double beta1 = tan(phi) / v;
double Aeq = asin( cos(beta1) * sin(azimuth) );
double f = (a - b) / a; //flattening
double beta = atan((1-f)*tan(phi));
double u2 = pow(cos(Aeq),2)*eu2;
//////////////////////////////----------------------------------------------
long double sigma1 = atan( tan(beta1)/ cos(azimuth) );
long double A = 1 + u2*(4096 + u2*(-768+u2*(320-175*u2))) / 16384;
long double B = u2*(256 + u2*(-128+u2*(74-47*u2)))/1024;
long double sigma = S / (b*A);
long double sigmaM = (2*sigma1 + sigma) /2;
long double d_w;
long double d_sigma;
////////////////////////////------------------------------------------------
double C;
double d_lambda;
long double sigma_last=invalid_constant;
do{
if(sigma_last != invalid_constant){
sigma = sigma_last;
}
sigma1 = atan( tan(beta1) / cos(A1) );
sigmaM = (2*sigma1 + sigma) / 2;
d_sigma = B*sin(sigma)*(cos(2*sigmaM)+(1/4)*B*(cos(sigma)
*(-1+2*pow(cos(2*sigmaM),2)))-(1/6)*B*cos(2*sigmaM)
*(-3+4*pow(sin(sigma),2))*(-3+4*pow(cos(2*sigmaM),2)));
sigma_last = sigma + d_sigma;
}
while(set_precision_14(sigma)<= set_precision_14(sigma_last) || set_precision_14(sigma)>= set_precision_14(sigma_last));
sigma = sigma_last;
*phi2 = atan((sin(beta1)*cos(sigma)+cos(beta1)*sin(sigma)*cos(azimuth))/((1-f)
*sqrt(pow(sin(Aeq),2)+pow((sin(beta1)*sin(sigma)-cos(beta1)*cos(sigma)*cos(azimuth)),2))));
d_w = (sin(sigma)*sin(azimuth))/(cos(beta1)*cos(sigma) - sin(beta1)* sin(sigma)*cos(azimuth));
C = (f/16)*pow(cos(Aeq),2)*(4+f*(4-3*pow(cos(Aeq),2)));
d_lambda = d_w - (1-C)*f*sin(azimuth)*(sigma + C*sin(sigma)*
(cos(2*sigmaM)+C*cos(sigma)*(-1+2*pow(cos(2*sigmaM),2))));
*lambda2 = lambda + d_lambda;
*azimuth2 = sin(Aeq) / (-sin(beta1)*sin(sigma)+cos(beta1)*cos(sigma)*cos(azimuth));
*azimuth2 = *azimuth2 * 180/M_PI;
*lambda2 = *lambda2 * 180/M_PI;
*phi2 = *phi2 * 180/M_PI;
}

Variable grouping providing different answers in optimized code

I've been attempting to unit test a C++ class I've written for Geodetic transforms.
I've noticed that a trivial grouping change of three variables greatly influences the error in the function.
EDIT : Here is the entire function for a compilable example:
Assume latitude, longitude and altitude are zero. Earth::a = 6378137 and Earth::b = 6356752.3 I'm working on getting benchmark numbers, something came up at work today and I had to do that instead.
void Geodesy::Geocentric2EFG(double latitude, double longitude, double altitude, double *E, double *F, double *G) {
double a2 = pow<double>(Earth::a, 2);
double b2 = pow<double>(Earth::b, 2);
double radius = sqrt((a2 * b2)/(a2 * pow<double>(sin(latitude), 2) + b2 * pow<double>(cos(longitude), 2)));
radius += altitude;
*E = radius * (cos(latitude) * cos(longitude));
*F = radius * (cos(latitude) * sin(longitude));
*G = radius * sin(latitude);
return;
}
Where all values are defined as double including those in Earth. The pow<T>() function is a recursive template function defined by:
template <typename T>
static inline T pow(const T &base, unsigned const exponent) {
return (exponent == 0) ? 1 : (base * pow(base, exponent - 1));
}
The code in question:
*E = radius * cos(latitude) * cos(longitude);
*F = radius * cos(latitude) * sin(longitude);
produces different results than:
*E = radius * (cos(latitude) * cos(longitude));
*F = radius * (cos(latitude) * sin(longitude));
What is the compiler doing in gcc with optimization level 3 to make these results 1e-2 different?
You have different rounding as floating point cannot represent all numbers:
a * b * c; is (a * b) * c which may differ than a * (b * c).
You may have similar issues with addition too.
example with addition:
10e10f + 1.f == 10e10f
so (1.f + 10e10f) - 10e10f == 10e10f - 10e10f == 0.f
whereas 1.f + (10e10f - 10e10f) == 1.f - 0.f == 1.f.

Calculating distances but the result is - 2147483648

Below is the code to calculate the distance
// creating array of cities
double x[] = {21.0,12.0,15.0,3.0,7.0,30.0};
double y[] = {17.0,10.0,4.0,2.0,3.0,1.0};
// distance function - C = sqrt of A squared + B squared
One issue is that the order of operations is messing you up (multiplication is done before subtraction)
Change
(x[c1] - x[c2] * x[c1] - x[c2]) + (y[c1] - y[c2] * y[c1] - y[c2])
to
((x[c1] - x[c2]) * (x[c1] - x[c2])) + ((y[c1] - y[c2]) * (y[c1] - y[c2]))
I would also recommend, just for clarity, doing some of those calculations on separate lines (clearly that's a style choice that I prefer, and I'm sure some would disagree). It should make no difference to the compiler though
double deltaX = x[c1] - x[c2];
double deltaY = y[c1] - y[c2];
double distance = sqrt(deltaX * deltaX + deltaY * deltaY);
In my opinion that makes for more maintainable (and less error prone, as in this instance) code. Note that, as rewritten, the order of operations does not require extra parentheses.
Remember operator precedence: a - b * c - d means a - (b * c) - d.
Do you want
(x[c1] - (x[c2] * x[c1]) - x[c2])
or
((x[c1] - x[c2]) * (x[c1] - x[c2]))
(x[c1] - x[c2] * x[c1] - x[c2]) will be similar to (x[c1] - (x[c2] * x[c1]) - x[c2]) because * has higher precedence than -.
I am going to go ahead and fix a couple of issues:
// creating array of cities
double x[] = {21.0,12.0,15.0,3.0,7.0,30.0};
double y[] = {17.0,10.0,4.0,2.0,3.0,1.0};
// distance function - C = sqrt of A squared + B squared
double dist(int c1, int c2) {
double z = sqrt (
((x[c1] - x[c2]) * (x[c1] - x[c2])) + ((y[c1] - y[c2]) * (y[c1] - y[c2])));
return z;
}
void main()
{
int a[] = {1, 2, 3, 4, 5, 6};
execute(a, 0, sizeof(a)/sizeof(int));
int x;
printf("Type in a number \n");
scanf("%d", &x);
int y;
printf("Type in a number \n");
scanf("%d", &y);
double z = dist (x,y);
cout << "The result is " << z;
}
This fixes the unused return value, and also fixes the order of operation, and incorrect variable type of int.