例如,
double a = 2.55;
double b = Math.Round(a, 1); // expected result is 2.5
Console.WriteLine(b); // 2.6
我們期望2.5存在的原因是最接近的 64 位 IEEE 754 浮點數2.55恰好是2.54999999999999982236431605997495353221893310546875,所以無論我們使用MidpointRounding.ToEven還是MidpointRounding.AwayFromZero該值都應該向下舍入2.5。
另一方面,“F”格式說明符似乎可以正確處理舍入。
double a = 2.55;
Console.WriteLine($"{a:F1}"); // 2.5
編輯:看起來 .NET 團隊正在跟蹤與Math.Round 此處基本相同的問題。據此,該問題可能會在即將到來的 .NET 7 中得到解決,但還不確定。
uj5u.com熱心網友回復:
您的實際問題的答案“.NET 中的 Math.Round 是否不正確地舍入某些值?” 是:是的。(好吧,微軟可能會爭辯說這種行為是有定義的,因此是正確的。)
其原因在以下檔案中進行了Math.Round()描述:
由于將十進制值表示為浮點數或對浮點值執行算術運算可能導致精度損失,因此在某些情況下,Round(Double, Int32, MidpointRounding) 方法可能不會按照指定的方式舍入中點值通過模式引數。這在以下示例中進行了說明,其中 2.135 舍入為 2.13 而不是 2.14。發生這種情況是因為該方法在內部將值乘以 10^digits,并且這種情況下的乘法運算會損失精度。
我們可以測驗一下:
double a = 2.55;
double c = a * Math.Pow(10, 1); // "a * 10.0" gives the same result.
Console.WriteLine(a.ToString("f16"));
Console.WriteLine(c.ToString("f16"));
輸出是:
2.5499999999999998
25.5000000000000000
可以看到乘以10^1后的值為25.5,在下一步的取整演算法中會進行取整。
你可以在這里查看實際的實作。
這有點繁瑣,但答案確實是“某物四舍五入”;)
uj5u.com熱心網友回復:
.NET 中舍入的默認實作是“Round half to even”,即“Bankers Rounding”。這意味著中點值朝最接近的偶數四舍五入。
uj5u.com熱心網友回復:
Math.Round(value,decimal)按預期作業。您將您的價值定義為2.55并認為您在 IEEE 754 中進行了四舍五入2.55,2.54999999...但這是錯誤的。帶小數的四舍五入將 10 的冪應用于四舍五入。因此,您2.55的小數點后 1 是應用 10 的單次冪,因此它成為在 IEEE 75425.5中完美表示的結果25.5。然后四舍五入26.0,然后除以該因子,2.6從而得到您的結果。
uj5u.com熱心網友回復:
因為 2.55 是中間值,所以它在舍入時使用約定。默認為“To Even”。所以在這種情況下,它會四舍五入到最接近的偶數 2.6。如果您使用 AwayFromZero 在這種情況下它會做同樣的事情,如果您四舍五入 2.65 它會給出不同的結果。
奇怪,我用字串格式化程式得到了相同的結果......?也許這是一種文化環境。另請參閱將 Double 轉換為字串:特定于文化
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/481111.html
上一篇:使用Dapper系結ASP.NETMVC時如何修復空的下拉串列?
下一篇:使用來自另一個函式的引數呼叫函式
