在.NET中,爲什麼System.Math.Round(1.035, 2, MidpointRounding.AwayFromZero)
產生1.03而不是1.04?我覺得我的問題的答案在於http://msdn.microsoft.com/en-us/library/ef48waz8.aspx的標題爲「給致電者的提示」部分,但我無法圍繞解釋說明。爲什麼在這種情況下System.MidpointRounding.AwayFromZero沒有取整?
回答
你的懷疑是完全正確的。帶小數部分的數字在.NET中以文字表示時默認爲doubles。雙精度(如浮點數)是十進制值的近似值,而不是精確的十進制值。它是可以用基-2(二進制)表示的最接近的值。在這種情況下,近似值在1.035的小方面是非常消失的。如果您在使用它工作的明確的小數寫它,你希望:
Console.WriteLine(Math.Round(1.035m, 2, MidpointRounding.AwayFromZero));
Console.ReadKey();
要理解爲什麼雙打和彩車工作他們的方式,想象代表十進制(數1/3或二進制,從遭受同樣的問題)。你不能將它翻譯爲.3333333 ....,這意味着要準確表示它需要無限量的內存。
計算機使用近似值解決此問題。我會詳細解釋,但我可能會弄錯。你可以在這裏閱讀所有關於它雖然:http://en.wikipedia.org/wiki/IEEE_754-1985
注意,默認值是* double。* 1.0隱式地是雙精度型,儘管它可以在1d或1.0d中顯式設置。浮點文字需要'f'後綴。 – 2012-02-10 00:57:47
固定,謝謝安迪爾 – 2012-02-10 01:01:14
@ChrisShain double確實是一個精確的值;它只是一個精確的二進制值,它可能或可能不是近似於文字所指示的精確十進制值。例如,二進制值「0.25d」正好等於十進制值0.25。另外,我認爲你的意思是「想象代表小數1/3」,因爲0.33333 ...是十進制表示,而不是二進制。二進制表示更像0.0101010101 ... – phoog 2012-02-10 01:04:33
在猜測我會說,內部1.035不能用二進制表示爲1.035,它可能(在引擎蓋下)1.0349999999999999,這就是爲什麼它下降。
只是一個猜測。
我相信你提到的例子是一個不同的問題;據我所知,他們說0.1不是以浮點形式存儲,正如0.1,但實際上由於浮點數如何存儲在二進制文件中,它實際上是稍微關閉的。因此,讓我們假設它實際上看起來更像0.0999999999999(或類似的),非常略微小於0.1 - 這樣稍微有點不會有太大的改變。呃,他們在說:不同的是,一個明顯的區別是將這個加到你的數字和四捨五入實際上會出錯,因爲即使數字非常接近,它仍然被認爲是「小於」.5的四捨五入。
如果我誤解了該網頁,我希望有人糾正我:)
我看不出它與您的電話,不過,因爲你是更加明確。也許它只是以類似的方式儲存你的號碼。
完全正確。 – 2012-02-10 00:57:02
+1「因爲如何以二進制形式存儲浮點數」。 – phoog 2012-02-10 01:07:28
I'ts因爲1.035的二進制表示更接近1.03比1.04
爲了獲得更好的成績做這種方式 -
decimal result = decimal.Round(1.035m, 2, MidpointRounding.AwayFromZero);
的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. 爲什麼在這種情況下
- 2. sched_yield在這種情況下做什麼?
- 3. .map()在這種情況下做什麼?
- 4. 什麼是在這種情況下
- 5. *在這種情況下做什麼?:
- 6. 什麼是在這種情況下
- 7. 爲什麼QWebFrame :: evalutateJavaScript在這種情況下什麼都不做?
- 8. 什麼是wrapper_descriptor,在這種情況下爲什麼是Foo .__ init __()?
- 9. 爲什麼bss在這種情況下有一些價值?
- 10. 爲什麼我們有這種情況下的輸出:S1S2?
- 11. mysql沒有連接,但爲什麼會發生這種情況
- 12. 在Pandas中,爲什麼groupby'key'列在這種情況下消失
- 13. 什麼是光標,它在做什麼(在這種情況下)?
- 14. 爲什麼是這種情況gc
- 15. 這種情況有什麼作用?
- 16. 這種情況有什麼問題?
- 17. 爲什麼'這'不是它在這種情況下應該是什麼?
- 18. 爲什麼sprintf()在這種情況下工作?
- 19. 爲什麼NHibernate FetchMode.Join在這種情況下工作?
- 20. 爲什麼Sweet Alert只能在這種情況下生產?
- 21. 爲什麼在這種情況下最大寬度不工作?
- 22. 爲什麼在這種情況下startActivityForResult()方法不起作用
- 23. 爲什麼autoboxing在這種情況下不適用於泛型?
- 24. 爲什麼在這種情況下需要componentWillReceiveProps?
- 25. 爲什麼在這種情況下我得到零錯誤?
- 26. 爲什麼'\ n'在這種情況下執行新的操作?
- 27. 爲什麼在這種情況下超時變量可共享?
- 28. 爲什麼在這種情況下PyGILState_Release(...)段錯誤?
- 29. 爲什麼在這種情況下會話到sql服務器?
- 30. 爲什麼.click()在這種情況下不起作用?
有趣的是,調用此方法與收益1.135 1.14的數值。 – 2012-02-10 00:51:44
「說明」基本上是基數爲2的數字。它不能精確地表示某些值*。您輸入1.035,內部表示可能是1.034999999982或其他。如果您對位數的確切表示方式感興趣,可能是System.Decimal是您的類型。特別是如果你正在處理財務價值。 – 2012-02-10 00:53:33
@KyleTrauberman這是因爲在1.135時你很幸運 - 近似值比1.135略高,而不像OP那樣。 – 2012-02-10 01:13:01