math - Why does C give different values to Python for this algorithm? -
i wrote short program in c perform linear interpolation, iterates give root of function given number of decimal points. far, function f(x):
long double f(long double x) { return (pow(x, 3) + 2 * x - 8); }
the program fails converge 1dp value. program updates variables , b, between root of f(x) lies, until , b both round same number @ given precision. using long doubles , above function, debugger shows first 2 iterations:
= 1.5555555555555556 = 1.6444444444444444
though should have been:
= 1.5555555555555556 = 1.653104925053533
the program fails update values after this. equation linear interpolation i'm using rearranged version of mathematical 1 given here , code i'm using c-version of python program wrote. why c implementation different values, despite same algorithm, , how can fix it?
ok i'm still getting hang of this, below have minimal, complete, , verifiable example:
#include <stdlib.h> #include <stdio.h> #include <math.h> long double a; long double b; long double c; // values interpolation long double fofa; long double fofb; long double fofc; // values f(a), f(b) , f(c) const int dp = 1; // number of decimal places accurate long double f(long double x) { return (pow(x, 3) + 2 * x - 8); } int main(void) { = 1; b = 2; while(roundf(a * pow(10, dp))/pow(10, dp) != roundf(b * pow(10, dp))/pow(10, dp)) { // while , b don't round same number... fofa = f(a); fofb = f(b); // resolve functions printf("so f(a) = %g, f(b) = %g\n", (double)fofa, (double)fofb); // print results c = (b * abs(fofa) + * abs(fofb)) / (abs(fofb) + abs(fofa)); // linear interpolation fofc = f(c); if(fofc < 0) { = c; } else if(fofc == 0) { = c; break; } else { b = c; } } printf("the root %g, %d decimal places, after %d iterations.\n", (double)a, dp, i); }
the function abs()
(from <stdlib.h>
) has signature int abs(int);
— getting integers calculations.
you should using long double fabsl(long double);
<math.h>
.
you should using powl()
instead of pow()
(long double
vs double
), , roundl()
instead of roundf()
(long double
vs float
).
make sure you're using correct types, in other words.
when you've fixed type problems, still have issue convergence. have helped if had produced mcve (minimal, complete, verifiable example). however, mcve can deduce question:
#include <math.h> #include <stdio.h> static inline long double f(long double x) { return(powl(x, 3) + 2 * x - 8); } int main(void) { long double = 1.0l; long double b = 2.0l; int dp = 6; while (roundl(a * powl(10, dp)) / powl(10, dp) != roundl(b * powl(10, dp)) / powl(10, dp)) { long double fofa = f(a); long double fofb = f(b); long double c = (b * fabsl(fofa) + * fabsl(fofb)) / (fabsl(fofb) + fabsl(fofa)); long double fofc = f(c); printf("a = %+.10lf, f(a) = %+.10lf\n", a, fofa); printf("b = %+.10lf, f(b) = %+.10lf\n", b, fofb); printf("c = %+.10lf, f(c) = %+.10lf\n", c, fofc); putchar('\n'); if (fofc < 0.0l) { = c; } else if (fofc == 0.0l) { = c; break; } else { b = c; } } printf("result: = %lg\n", a); return 0; }
the output is:
a = +1.0000000000, f(a) = -5.0000000000 b = +2.0000000000, f(b) = +4.0000000000 c = +1.5555555556, f(c) = -1.1248285322 = +1.5555555556, f(a) = -1.1248285322 b = +2.0000000000, f(b) = +4.0000000000 c = +1.6531049251, f(c) = -0.1762579238 = +1.6531049251, f(a) = -0.1762579238 b = +2.0000000000, f(b) = +4.0000000000 c = +1.6677455452, f(c) = -0.0258828049 = +1.6677455452, f(a) = -0.0258828049 b = +2.0000000000, f(b) = +4.0000000000 c = +1.6698816424, f(c) = -0.0037639074 = +1.6698816424, f(a) = -0.0037639074 b = +2.0000000000, f(b) = +4.0000000000 c = +1.6701919841, f(c) = -0.0005465735 = +1.6701919841, f(a) = -0.0005465735 b = +2.0000000000, f(b) = +4.0000000000 c = +1.6702370440, f(c) = -0.0000793539 = +1.6702370440, f(a) = -0.0000793539 b = +2.0000000000, f(b) = +4.0000000000 c = +1.6702435859, f(c) = -0.0000115206 = +1.6702435859, f(a) = -0.0000115206 b = +2.0000000000, f(b) = +4.0000000000 c = +1.6702445357, f(c) = -0.0000016726 = +1.6702445357, f(a) = -0.0000016726 b = +2.0000000000, f(b) = +4.0000000000 c = +1.6702446735, f(c) = -0.0000002428 = +1.6702446735, f(a) = -0.0000002428 b = +2.0000000000, f(b) = +4.0000000000 c = +1.6702446936, f(c) = -0.0000000353 = +1.6702446936, f(a) = -0.0000000353 b = +2.0000000000, f(b) = +4.0000000000 c = +1.6702446965, f(c) = -0.0000000051 = +1.6702446965, f(a) = -0.0000000051 b = +2.0000000000, f(b) = +4.0000000000 c = +1.6702446969, f(c) = -0.0000000007 = +1.6702446969, f(a) = -0.0000000007 b = +2.0000000000, f(b) = +4.0000000000 c = +1.6702446970, f(c) = -0.0000000001 = +1.6702446970, f(a) = -0.0000000001 b = +2.0000000000, f(b) = +4.0000000000 c = +1.6702446970, f(c) = -0.0000000000 = +1.6702446970, f(a) = -0.0000000000 b = +2.0000000000, f(b) = +4.0000000000 c = +1.6702446970, f(c) = -0.0000000000 = +1.6702446970, f(a) = -0.0000000000 b = +2.0000000000, f(b) = +4.0000000000 c = +1.6702446970, f(c) = -0.0000000000 = +1.6702446970, f(a) = -0.0000000000 b = +2.0000000000, f(b) = +4.0000000000 c = +1.6702446970, f(c) = -0.0000000000
the reason infinite loop clear; difference between a
, b
not small fraction. need review convergence criterion. should comparing fofc
0.0
within given number of decimal places — or along lines.
Comments
Post a Comment