在.NET中,为什么会System.Math.Round(1.035, 2, MidpointRounding.AwayFromZero)产生1.03而不是1.04?我觉得我的问题的答案在于http://msdn.microsoft.com/en-us/library/ef48waz8.aspx上标有"呼叫者注意"的部分,但是我无法绕过说明.
Chr*_*ain 31
你的怀疑是完全正确的.具有小数部分的数字(在.NET中表示为文字时)默认为双精度数.双精度(如浮点数)是十进制值的近似值,而不是精确的十进制值.它是可以用base-2(二进制)表示的最接近的值.在这种情况下,近似值在1.035的小范围内如此消失.如果使用显式Decimal编写它,它可以按预期工作:
Console.WriteLine(Math.Round(1.035m, 2, MidpointRounding.AwayFromZero));
Console.ReadKey();
Run Code Online (Sandbox Code Playgroud)
要理解为什么双精度浮点数和浮点数按照它们的方式工作,想象一下用十进制数表示1/3(或二进制数,它会遇到同样的问题).你不能 - 它转换为.3333333 ....,意味着准确地表示它将需要无限的内存.
计算机使用近似值来解决这个问题.我会详细解释如何,但我可能会弄错.你可以在这里阅读所有相关内容:http://en.wikipedia.org/wiki/IEEE_754-1985
小智 9
1.035d的二进制表示是0x3FF08F5C28F5C28F,实际上是1.03499999999999992006394222699E0,因此System.Math.Round(1.035,2,MidpointRounding.AwayFromZero)产生1.03而不是1.04,所以它是正确的.
但是,4.005d的二进制表示为0x4010051EB851EB85,即4.00499999999999989341858963598,因此System.Math.Round(4.005,2,MidpointRounding.AwayFromZero)应该产生4.00,但它产生4.01这是错误的(或智能'修复').如果你在MS SQL中检查它选择ROUND(CAST(4.005 AS float),2),它是4.00我不明白为什么.NET应用这个"智能修复"会让事情变得更糟.
您可以在http://www.binaryconvert.com/convert_double.html上查看双精度的二进制表示
我是因为1.035的BINARY表示接近1.03而不是1.04
为了更好的结果,这样做 -
decimal result = decimal.Round(1.035m, 2, MidpointRounding.AwayFromZero);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
25185 次 |
| 最近记录: |