【发布时间】:2017-08-05 23:20:42
【问题描述】:
我有以下代码:
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));
但是,无论是从 VS2012 还是 VS2015 编译(都具有“标准”设置),它都会返回不同的结果
在 VS2012 中
0,56000000238418600000
0,55999998748302500000
在 VS2015 中:
0,56000000238418600000
0,56000000238418600000
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]
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]
我们可以看到两种情况下的反汇编都不相同,这正常吗?这可能是 VS2012 或 VS2015 中的错误吗?或者这种行为是否由某些已更改的特定设置控制? 谢谢!
【问题讨论】:
-
我的第一个猜测是,roslyn 有不同的构建参数和/或不同的 .net 版本会导致这种情况
-
这是调试还是发布? 64位构建的结果是什么? 32 位构建使用 x87,因此它不像 SSE2 那样快速和一致
-
程序集列表相同,但地址不同。数据段选择器 ds:[...] 指向编译时常量(显然 0.02f * 28f 的结果被烘焙到程序集中)。运行时没有乘法。
-
@dlatikay 2012 版本有 dword 指令,而其他地方只有 qword 指令(我不知道它是否相关)
-
doubles 总是给出不同的结果——它是一个二进制浮点数。它会尝试尽可能接近正确的数字,但并非总是如此。它还取决于在后台为其分配了多少内存。
标签: c# visual-studio visual-studio-2012 visual-studio-2015