LEE*_*hon 3 c# floating-point precision casting
在阅读了这个问题以及这个msdn博客之后,我尝试了一些示例来对此进行测试:
Console.WriteLine(0.8-0.7 == 0.1);
Run Code Online (Sandbox Code Playgroud)
是的,预期输出为False。因此,我尝试将表达式的两端都强制转换为double,float以查看是否可以获得不同的结果:
Console.WriteLine((float)(0.8-0.7) == (float)(0.1));
Console.WriteLine((double)(0.8-0.7) == (double)(0.1));
Run Code Online (Sandbox Code Playgroud)
第一行输出True但第二行输出False,为什么会发生这种情况?
此外,
Console.WriteLine(8-0.7 == 7.3);
Console.WriteLine(8.0-0.7 == 7.3);
Run Code Online (Sandbox Code Playgroud)
上面的两行都给出True甚至不进行强制转换。还有...
Console.WriteLine(18.01-0.7 == 17.31);
Run Code Online (Sandbox Code Playgroud)
此行输出False。如果将两者都用浮点数相减,则如何从减法18.01中减去8的差?
我试图阅读博客和问题,但似乎找不到其他答案。有人可以向我解释为什么所有这些都是以莱曼的语言发生的吗?先感谢您。
编辑:
Console.WriteLine(8.001-0.001 == 8); //this return false
Console.WriteLine(8.01-0.01 == 8); //this return true
Run Code Online (Sandbox Code Playgroud)
注意:我正在使用.NET小提琴在线c#编译器。
在中0.8-0.7 == 0.1,没有任何文字可以精确地用表示double。最接近的可代表值是0.8的0.8000000000000000444089209850062616169452667236328125、0.7的0.6999999999999999555910790149937383830547332763671875和0.1的0.1000000000000000055511151231257827021181583404541015625。当减去前两个时,结果为0.100000000000000088817841941970012523233890533447265625。由于这不等于第三个,因此0.8-0.7 == 0.1计算为false。
在(float)(0.8-0.7) == (float)(0.1),结果0.8-0.7和0.1各自转化成float。float最接近前者的值0.1000000000000000055511151231257827021181583404541015625为0.100000001490116119384765625。float最接近后者的值0.100000000000000088817841970012523233890533447265625是0.100000001490116119384765625。由于这些相同,因此(float)(0.8-0.7) == (float)(0.1)评估为true。
在(double)(0.8-0.7) == (double)(0.1),结果0.8-0.7和0.1各自转化成double。由于它们已经double存在,因此没有任何效果,其结果与相同0.8-0.7 == 0.1。
的C#规范,版本5.0表示float和double是IEEE-754的32位和64位浮点类型。我没有看到它明确声明它们是二进制浮点格式而不是十进制格式,但是所描述的特征使这一点显而易见。该规范还指出,除以下例外情况外,通常使用IEEE-754算术,取整为最近(大概取整为整数)。
C#规范允许比标称类型更精确地执行浮点运算。第4.1.6节说:“ ...浮点运算的执行精度可能高于运算的结果类型……”这通常会使浮点表达式的分析复杂化,但是在这种情况下它并不涉及我们,0.8-0.7 == 0.1因为唯一可应用的操作是0.7from 的减法0.8,并且这些数字在同一binade中(在浮点表示中具有相同的2的幂),因此减法的结果可精确表示,并且额外的精度不会改变结果。只要源文本的转换0.8,0.7以及0.1以double不使用额外的精度和演员来float产生float没有额外精度的,结果将如上所述。(C#标准在第6.2.1节中说,从double到的转换会float产生一个float值,尽管它没有明确声明此时不能使用额外的精度。)
在中8-0.7 == 7.3,对于,我们有8个8,7.29999999999999982236431605997495353221893310546875对于7.3,0.6999999999999999555555790790149937383830547332763671875 0.7和7.29999999999999982236431605997495353221893310546875为8-0.7,所以结果为true。
请注意,C#规范允许的附加精度可能会影响的结果8-0.7。在这种情况下使用额外精度的AC#实现在这种情况下可能会产生false,因为它将为获得不同的结果8-0.7。
在中18.01-0.7 == 17.31,我们有18.010000000000001563194018672220408916473388671875为18.01,0.6999999999999999555910790149937383830547332763671875为0.7,17.309999999999998721023075631819665431976318359375为17.31,17.31000000000000227373675443232059478759765625为18.01-0.7,所以结果为假。
如果将两者都用浮点数相减,则如何从减法18.01中减去8的差?
18.01大于8,并且在其浮点表示形式中需要2的更大幂。同样,的结果18.01-0.7大于的结果8-0.7。这意味着有效位中的位(浮点表示的小数部分,由2的幂进行缩放)表示更大的值,从而导致浮点运算中的舍入误差通常更大。通常,浮点格式具有固定的跨度-从保留的高位到保留的低位有固定的距离。当您更改为左侧有更多位(高位)的数字时,右侧有一些位(低位)被推出,结果将改变。
| 归档时间: |
|
| 查看次数: |
86 次 |
| 最近记录: |