{
double A = 373737.0;
double B;
B = A*A*A 0.37/A - A*A*A - 0.37/A;
printf("The value of B is %f.\n", B);
}
In this C code, why is the value of B not zero, but instead -0.000001?
CodePudding user response:
Several people have mentioned in comments that neither 0.37 nor 0.37/373737.0 can be represented accurately in binary floating point, which is true. But that's a bit of a red herring. You could replace 0.37/A
with 1
, which is clearly representable accurately in floating point, and you'd still get an odd result. Perhaps that odd result would be more revealing. It's certainly worth trying the experiment yourself.
Floating point arithmetic might turn out differently on different machines (although these days, that's uncommon) but under most circumstances, in a single program run on a single machine, 0.37/373737.0 will always be the same value. So you might expect that the two instances of 0.37/A
will cancel out.
And they would have, had you written A*A*A - A*A*A 0.37/A - 0.37/A
. But that's not the order you did the operations, and the result is the round-off error that you experienced. The problem is that A*A*A
is quite a large number, well outside the range of integers which can be represented accurately in a 64-bit double. And moreover, 0.37/A
is a small number. Consequently, A*A*A 0.37/A
is exactly the same as A*A*A
; the exact sum is quite a bit smaller than the next larger double-precision value.
Thus, A*A*A 0.37/A - A*A*A
is 0; the 0.37/A
simply vanishes. And then A*A*A 0.37/A - A*A*A - 0.37/A
is -0.37/A
, which is approximately 0.000001 (if you printed it with more precision, you'd see a more accurate output).
Standard C does not allow the compiler to regroup floating point computations, because it would make it impossible to predict the result. If you need a particular order of evaluation to avoid numeric instability, you have to do it yourself. (GCC does provide the -funsafe-math-optimizations
flag, which can violate the C standard, produce unpredictable results, and sometimes accidentally produce the result you expected. Don't use it. It's unsafe.)
And part of learning how to write numerical programs is learning how to reorder your computations to avoid this type of error. One rule is, never subtract two large but similar numbers, since that will produce a wildly inaccurate result. (That's the rule which your expression breaks.)
Any good text book on numerical computation should go into much more detail about these issues. You could also start with the venerable essay, already mentioned in comments, What every computer scientist should know about floating point arithmetic.
CodePudding user response:
If your math gives irrational or repeating numbers after one or more opraters is done, the computer will cut it off or rounded, therefor, it's not 0. This is called round off error.
CodePudding user response:
There are many reason may be you expression opration become out of range of double variable.You are printing double value using float format pacifier.Resolve this may it will give you desired output.