pmc*_*avy 2 c# precision double ieee-754
考虑以下 C# 代码...
double x = Math.Round(72.6d, 2, MidpointRounding.ToZero);
double y = Math.Round(82.6d, 2, MidpointRounding.ToZero);
Run Code Online (Sandbox Code Playgroud)
x成为72.59并y成为82.6。
但为什么?通过这个IEEE754 转换器,两者的小数部分是相同的。那么为什么他们不给出相同的结果呢?
我可以通过执行以下操作来解决该问题(double)Math.Round(Convert.ToDecimal(72.6d), 2, MidpointRounding.ToZero)。但我更感兴趣的是知道为什么它似乎没有按预期工作的答案。
根据Microsoft 文档,MidpointRounding.ToZero不执行 \xe2\x80\x9cmidpoint 舍入。\xe2\x80\x9d 看来 Microsoft 在这里搞砸了界面:
MidpointRounding最初创建为一个枚举,用于在四舍五入到最接近的偶数 ( ToEven) 和舍入到最接近的远离零 ( AwayFromZero) 之间进行选择。Math.Round:向负无穷大舍入 ( ToNegativeInfinity)、向正无穷大舍入 ( ToPositiveInfinity) 和向零舍入 ( ToZero)。请注意,这些方向不会四舍五入到最接近的方向;他们转向其中一个方向。例如,对于ToZero,3.1、3.2、3.5、3.6 和 3.8 均四舍五入为 3。RoundingMethod,而是将这些新值添加为MidpointRounding.结果是,所有五种舍入方法都具有以下形式的名称,即使其中只有两种是与中点相关的舍入到最接近的方法。MidpointRounding.Name
(我们还看到使用To而不是术语不敏感Toward。3.4 舍入到 3,即朝零舍入。它没有舍入到零。IEEE 754 使用 \xe2\x80\x9ctoward\xe2\x80\x9d 作为这些舍入方法。)
除此之外,本文档告诉我们Math.Round通过乘以 10 n并四舍五入到整数来进行操作,而不是对原始数字进行正确的四舍五入确定,我们可以看到会发生什么:
double,产生最接近的可表示值 72.599999999999994315658113919198513031005859375。乘以 100,得到 7259.9999999999990905052982270717620849609375。向零方向舍入为整数,生成 7259。除以 100,生成 72.590000000000003410605131648480892181396484375,如果使用的位数少于 17 个,则打印为 72.59。double,产生 82.599999999999994315658113919198513031005859375。乘以 100,得到 8260。这种情况与之前的情况之间的差异是由于实数相对于可表示数所处的位置的偶然性。然后将 8260 除以 100,生成 82.599999999999994315658113919198513031005859375,如果使用的数字少于 16 个,则打印为 82.60。