BUG: A numeric result is not rounded as expected when you explicitly convert a mathematical expression to a double numeric type in Visual C++ .NET or in Visual C++ 2005 (907296)



The information in this article applies to:

  • Microsoft Visual C++ .NET (2003)
  • Microsoft Visual C++ .NET (2002)
  • Microsoft Visual C++ 2005 Express Edition

SYMPTOMS

Consider the following scenario. You explicitly convert a mathematical expression to a double numeric type in Microsoft Visual C++ .NET or Microsoft Visual C++ 2005. In this scenario, the numeric result of the mathematical expression is not rounded as expected.

CAUSE

When the value of a mathematical expression is calculated, intermediate values that are held in the register may not be converted from one type to another type. The ignored conversions affect the rounding of the numeric final result.

STATUS

Microsoft has confirmed that this is a bug in the Microsoft products that are listed in the "Applies to" section.

MORE INFORMATION

The following code sample illustrates this issue.

Note This code sample must be compiled on a Intel Pentium x86-based computer, and the first line of the code sample must be the command-line switch -fp:precise or the command line switch -fp:strict.
1	//Insert the command-line switch here.
2	#include <math.h>
3	#include <stdio.h>
4	#include <float.h>

5	int main()
6	{ 
7	// assume _controlfp(_PC_53, _MCW_PC);
8	double m = DBL_MAX;
9	double d0, d1, d2;
10	d0=m+m-m;
11	d1=double(m+m)-m;
12	d2=m+m;
13	d2=d2-m;

14	printf("d0=%lf\n",d0);
15	printf("d1=%lf\n",d1);
16	printf("d2=%lf\n",d2);
17	if (d1!=d2)
18	{
19	if (d1==d0)
20	printf("ERROR: explicit double rounding was not honored");
21	else
22	printf("ERROR: expected d1==d2, d1!=d2 on x86");
23	return -1;
24	} 
25	printf("Passed");
26	return 0;
27	}
In line 8, the variable m is set to the largest numeric value for a double numeric type. In line 9, the variables d0, d1, and d2 are set to the double numeric type. In Visual C++, all calculations store intermediate values in the register. The register of an Intel Pentium processor is set to double precision and has a wider long-double exponent.

In line 10, the intermediate value m+m-m is calculated in the register. Then, the intermediate value is converted to a double numeric type. Finally, the converted intermediate value is assigned to the variable d0.

In line 11, the intermediate value m+m is calculated in the register. Then, the intermediate value should be converted to a double numeric type. However, the intermediate value is not converted because of the issue that is mentioned in the "Symptoms" section. Next, m is subtracted from the unconverted intermediate value. This subtraction creates a second intermediate value. Then, the second intermediate value is converted to a double numeric type. Finally, the second intermediate value is assigned to the variable d1.

In line 12, the intermediate value m+m is calculated in the register. Then, the intermediate value is converted to a double numeric type. Finally, the converted intermediate value is assigned to the variable d2.

In line 13, the intermediate value d2-m is calculated in the register. Then, the intermediate value is converted to a double numeric type. Finally, the converted intermediate value is assigned to the variable d2.

The issue that is mentioned in the "Symptoms" section causes the following conditions to be true:
  • d0 is equal to d1
  • d1 is not equal to d2
You expect the following conditions to be true:
  • d0 is not equal to d1
  • d1 is equal to d2

Modification Type:MajorLast Reviewed:1/6/2006
Keywords:kbnofix kbbug KB907296 kbAudDeveloper