lez*_*lon 5 c# visual-studio visual-studio-2012 visual-studio-2015
我有以下代码:
float a = 0.02f * 28f;
double b = (double)a;
double c = (double)(0.02f * 28f);
Console.WriteLine(String.Format(" {0:F20}", b));
Console.WriteLine(String.Format(" {0:F20}", c));
Run Code Online (Sandbox Code Playgroud)
然而,无论是从VS2012还是VS2015(均具有"标准"设置)编译,它都会返回不同的结果
在VS2012
0,56000000238418600000
0,55999998748302500000
Run Code Online (Sandbox Code Playgroud)
在VS2015中:
0,56000000238418600000
0,56000000238418600000
Run Code Online (Sandbox Code Playgroud)
VS2012解散:
float a = 0.02f * 28f;
0000003a mov dword ptr [ebp-40h],3F0F5C29h
double b = (double)a;
00000041 fld dword ptr [ebp-40h]
00000044 fstp qword ptr [ebp-48h]
double c = (double)(0.02f * 28f);
00000047 fld qword ptr ds:[001D34D0h]
0000004d fstp qword ptr [ebp-50h]
Run Code Online (Sandbox Code Playgroud)
VS2015解散:
float a = 0.02f * 28f;
001E2DE2 mov dword ptr [ebp-40h],3F0F5C29h
double b = (double)a;
001E2DE9 fld dword ptr [ebp-40h]
001E2DEC fstp qword ptr [ebp-48h]
double c = (double)(0.02f * 28f);
001E2DEF fld dword ptr ds:[1E2E7Ch]
001E2DF5 fstp qword ptr [ebp-50h]
Run Code Online (Sandbox Code Playgroud)
我们可以看到两种情况下的反汇编都不相同,这是正常的吗?这可能是VS2012或VS2015中的错误吗?或者这种行为是由一些特定的设置控制的?谢谢!
这里的问题是,在Roslyn编译器中,在编译时完成的常量浮点计算与早期版本的执行方式略有不同 - 这导致了不同的行为.
但是,由于C#标准的这一部分,这不是一个错误:
4.1.6浮点类型
可以以比操作的结果类型更高的精度执行浮点运算.例如,某些硬件体系结构支持"扩展"或"长双"浮点类型,其范围和精度比double类型更大,并使用此更高精度类型隐式执行所有浮点运算.只有在性能成本过高的情况下,才能使这种硬件架构以较低的精度执行浮点运算,而不是要求实现放弃性能和精度,C#允许更高精度的类型用于所有浮点运算.除了提供更精确的结果外,这几乎没有任何可衡量的影响.但是,在x*y/z形式的表达式中,乘法产生的结果超出双范围,但随后的除法将临时结果带回双范围,表达式的计算结果更高范围格式可能导致产生有限结果而不是无穷大.要将浮点类型的值强制为其类型的精确精度,可以使用显式强制转换.
发生的事情是您正在看到由上述结果导致的未定义行为的结果,其中Roslyn编译器在编译时完成的浮点计算使用与早期编译器在编译时完成的计算不同的精度.
请注意,Roslyn编译器的初始版本中确实存在一个错误,该错误由Update 2修复:https://github.com/dotnet/roslyn/issues/7262 - 但这只是一个感兴趣的点,并非直接与VS2012和VS2015(使用Update 2)之间的结果差异有关.
有关详细信息,请参阅以下内容:
| 归档时间: |
|
| 查看次数: |
230 次 |
| 最近记录: |