ID Number: Q42761
5.10 6.00 6.00a 6.00ax 7.00 | 5.10 6.00 6.00a
MS-DOS | OS/2
Summary:
SYMPTOMS
The program below fails when compiled with default optimizations in
Microsoft C versions 5.1, 6.0, 6.0a, and 6.0ax. It prints the
following with default optimizations enabled:
23.31 * 100 = 2330.
However, if compiled with /Od it prints:
23.31 * 100 = 2331
The problem seems to be in the conversion of the double to int;
the rounding seems to be done incorrectly.
RESOLUTION
To avoid this problem, use the /Op option when compiling. The /Op
switch forces in-memory storage of intermediate results. /Op can be
combined with other optimizations (for instance, /Oxp).
STATUS
Microsoft C/C++ version 7.0 does not exhibit this problem.
More Information:
When the code is optimized, the result of the division is kept on the
floating-point stack rather than being stored into memory and reloaded
onto the stack. This causes precision problems, because the numbers on
the stack are stored in extended (10- byte) precision, while doubles in
memory are stored using 8 bytes.
Note that the constant 23.31 cannot be represented exactly in the
binary floating-point scheme used by Microsoft C. The fact that it is
represented slightly small and then multiplied by 100 (magnifying the
error) contributes to this problem.
Sample Code
-----------
/* Compile options needed: none
*/
#include <stdio.h>
void main( )
{
int a;
double f;
f = 23.31;
f = f * 100;
a = (int) f;
printf( "23.31 * 100 = %d\n", a );
}
Additional reference words: 5.00 5.10 6.00 6.00a 6.00ax 7.00