[英]C# loss of precision when dividing doubles
我知道這已經一次又一次地討論了,但是我似乎無法得到一個一步一步的雙重划分的最簡單的例子,導致C#的預期的,不完整的結果 - 所以我想知道是否也許有一些編譯器標志或其他奇怪的我沒有想到的。 考慮這個例子:
double v1 = 0.7;
double v2 = 0.025;
double result = v1 / v2;
當我在最后一行之后斷開並在VS調試器中檢查它時,“result”的值是27.999999999999996。 我知道我可以通過更改為“十進制”來解決它,但在周圍程序的情況下這是不可能的。 像這樣的兩個低精度雙倍不能分成28的正確值是不奇怪的? 對Math.Round來說唯一的解決方案是結果嗎?
像這樣的兩個低精度雙倍不能分成28的正確值是不奇怪的?
不,不是真的。 在double
類型中,0.7和0.025都不能精確表示。 涉及的確切價值是:
0.6999999999999999555910790149937383830547332763671875
0.025000000000000001387778780781445675529539585113525390625
現在你感到驚訝的是,該部門並沒有給出28分? 垃圾進垃圾出...
如你所說,正確表示十進制數的正確結果是使用decimal
。 如果你的程序的其余部分使用了錯誤的類型,那只意味着你需要解決更高的問題:獲得錯誤答案的成本,或者更改整個程序的成本。
它與double
數字的“簡單”或“小”無關。 嚴格地說, 0.7
或0.025
都不能存儲為計算機內存中的那些數字,因此如果你的精確度很高,那么對它們進行計算可能會提供有趣的結果。
所以是的,使用decimal
或圓形。
通過類比來解釋這個:
想象一下,你在基數3工作。在基數3中,0.1是(十進制)1/3,或0.333333333'。
因此,您可以在基數3中精確表示1/3(十進制),但在嘗試以十進制表示時會出現舍入錯誤。
好吧,你可以用一些十進制數得到完全相同的東西:它們可以用十進制精確表示,但它們不能用二進制表示; 因此,你會得到舍入錯誤。
簡短回答你的第一個問題:不,這並不奇怪。 浮點數是實數的離散近似值,這意味着當您進行算術運算時,舍入誤差將傳播和縮放。
Theres是一個稱為數值分析的整個數學領域,它基本上處理了在使用這種近似時如何最小化誤差。
這是通常的浮點不精確。 並非每個數字都可以表示為double,並且這些次要表示不准確性會加起來。 這也是你不應該將雙打與精確數字進行比較的原因。 我只是測試了它, result.ToString()
double.ToString()
顯示28
(也許某種舍入發生在double.ToString()
?)。 result == 28
雖然返回了false
。 並且(int)result
返回27
。 所以你只需要期待那樣的不精確。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.