INF: Use /Op to Avoid Loss of Precision from Optimization

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