为什么(双)0.6f>(双)(6 / 10f)?

这是我的电脑上发生的事情:

(double)(float)0.6 = 0.60000002384185791 (double)0.6f = 0.60000002384185791 (double)(6/10f) = 0.6 (double)(float)(6/10f) = 0.6 

6 / 10f也是浮子,怎么可以精确到0.6?
在我看来(双)(6 / 10f)也应该是0.60000002384185791。 有人可以帮忙解释一下吗? 谢谢!

首先,重要的是要记住0.6不能精确地表示为float然而它可以精确地表示为double精度(浮点运算的不精确性有很好的记录,如果不清楚为什么0.6不能准确地表示为浮点数,试试这个链接 )

您之所以看到上述行为,原因在于编译器 – 如果您查看reflection器中已编译的程序集,那么此处的内容会更清晰一些:

更新我已经更改了代码,因此它不使用Console.WriteLine ,因为我意识到编译器正在为您选择一个重载,这使情况混乱)

 // As written in source var j = (double)(float)0.6; var k = (double)0.6f; var l = (double)(6/10f); var m = (double)(float)(6/10f); // Code as seen by Reflector double j = 0.60000002384185791; double k = 0.60000002384185791; double l = 0.6; double m = 0.6; 

为什么编译器选择以这种特殊的方式编译是超出我的(fyi,这是关闭优化的全部)

其他一些有趣的案例:

 // Code var a = 0.6; var b = (double)0.6; var c = 0.6f; var d = (float)0.6; var e = 6 / 10; var f = 6 / (10f); var g = (float)(6 / 10); var h = 6 / 10f; var i = (double)6 / 10; // Prints out 0.60000002384185791 double n = (float)0.6; double o = f; // As seen by Reflector double a = 0.6; double b = 0.6; float c = 0.6f; float d = 0.6f; int e = 0; float f = 0.6f; float g = 0f; float h = 0.6f; double i = 0.6; double n = 0.60000002384185791; double o = f; 

编译器似乎只是在几个特殊情况下执行上述技巧,为什么只有在转换为double时才会执行此操作完全超出我的范围!

其余的时间似乎做了一些技巧,使浮点运算似乎工作,实际上它通常不会。

它似乎在结果四舍五入。 您是否以精确的必要数字显示结果? 您可以使用Jon Skeet中的此c#类来获取打印出的结果的精确数字表示。

请注意, ToString()不会始终打印所有数字,Visual Studio调试器也不会。

如果我是一个博彩人,我会说区别在于强制发生的地方。 在后两个例子(6 / 10f的例子)中,有两个文字都是整数(整数6和浮点数10.00000000 ……)。 这种划分似乎是在强制之后发生的,至少在您正在使用的编译器中。 在前两个示例中,您有一个小数浮点字面值(0.6),它不能充分表示为float的尾数内的二进制值。 将该值强制转换为双倍不能修复已经完成的损坏。

在产生完全一致结果的环境中,除法在强制加倍之前发生(6将被强制转换为浮点以使除法与10匹配,除法在浮动空间中执行,然后结果被强制到一个双)。