2013-08-21 66 views
4

當鑄造小數變成雙倍時,我遇到了一個奇怪的問題。鑄造小數變成雙倍的奇怪行爲

下面的代碼返回true:

Math.Round(0.010000000312312m, 2) == 0.01m //true 

然而,當我投這加倍返回false:

(double)Math.Round(0.010000000312312m, 2) == (double)0.01m //false 

,當我想用​​Math.Pow我已經經歷過這個問題,由於沒有Math.Pow超載,所以被迫將十進制數轉換爲double。

這是記錄的行爲?如果我被迫將小數點數加倍,我該如何避免它?從Visual Studio

截圖:

Screenshot from Visual Studio

鑄造Math.Round翻倍我下面的結果:

(double)Math.Round(0.010000000312312m, 2) 0.0099999997764825821 double 
(double)0.01m 0.01 double 

UPDATE

好吧,我再現問題如下:

  1. 當我運行WPF應用程序並檢查剛剛啓動後的手錶輸出時,我得到了真正的空項目。
  2. 有一部分應用程序將值從滑塊發送到計算算法。我得到錯誤的結果,我把計算方法上的斷點。現在,當我查看觀察窗口中的值時,我得到了錯誤(沒有任何修改,我只是刷新觀察窗口)。
  3. 只要我在一些較小的項目中重現問題,我會在這裏發佈。

UPDATE2

不幸的是,我無法在較小的項目重現該問題。我認爲埃裏克的答案解釋了原因。

+1

你的第二條語句也返回'true'。 – Rotem

+3

你不應該使用平等檢查雙重使用一些epsilon值 – ne2dmar

+0

第二個聲明對我來說也是如此,在VS2012,.NET 4.0 – Jonesopolis

回答

11

人們都在報道這裏的評論有時候比較的結果是真實的,有時它是錯誤的。

不幸的是,這是可以預料的。C#編譯器,抖動器和CPU全部允許在以上執行雙精度運算,更多比64位精度,,因爲他們認爲合適。這意味着有時看起來像「相同」計算的結果可以在一次計算中以64位精度完成,在另一次計算中可以以80位或128位精度完成,並且這兩個結果在其最後一位可能不同。

讓我確定你明白我的意思是「他們認爲合適」。 您可以得到不同的結果。您可以在調試和零售中獲得不同的結果。如果編譯器在常量中執行計算,並且如果使運行時在運行時執行計算,則可以得到不同的結果。調試器運行時可以得到不同的結果。您可以在運行時和調試器的表達式計算器中獲得不同的結果。 任何原因。雙算術是本質上不可靠。這是由於浮點芯片的設計造成的;對這些芯片的雙重算術運算不會變得更加可重複,而且不會有相當大的性能損失。

由於這個和其他原因你應該幾乎永遠不會比較兩個雙打確切的相等。相反,減去雙打,並看看差異的絕對值是否小於合理界限。

而且,你明白爲什麼舍入兩位小數是一個困難的事情是很重要的。一個非零的有限雙數是形式(1 + f)x 2的數字,其中f是分母的冪爲2的分數,e是指數。顯然,以這種形式表示0.01是不可能的,因爲沒有辦法讓分母等於兩個冪等於分母的十的冪。

雙0.01實際上是二進制數1.0100011110101110000101000111101011100001010001111011×2 -7,這在十進制是0.01000000000000000020816681711721685132943093776702880859375。那就是最接近你可能會達到0.01的雙倍。如果你需要代表,那麼那個值,然後使用小數點。這就是爲什麼它叫十進制

順便說一句,我在StackOverflow上多次回答了這個問題的變化。例如:

Why differs floating-point precision in C# when separated by parantheses and when separated by statements?

另外,如果你需要「拆開」雙看什麼它的位,我颳起了一段時間後這個方便的代碼是非常有用的。它要求你安裝Solver Foundation,但這是免費下載。

http://ericlippert.com/2011/02/17/looking-inside-a-double/

0

這是記錄的行爲。小數數據類型比double類型更精確。所以當你從十進制轉換爲雙精度時,可能會丟失數據。這就是爲什麼你需要做一個明確的類型轉換。

更多信息請參見下面的MSDN C#參考:

十進制數據類型:http://msdn.microsoft.com/en-us/library/364x0z75(v=vs.110).aspx

雙數據類型:http://msdn.microsoft.com/en-us/library/678hzkk9(v=vs.110).aspx

鑄造和類型轉換:http://msdn.microsoft.com/en-us/library/ms173105.aspx

+2

此解釋並未解釋上述評論中顯示的結果:即有時結果是真實的,有時是錯誤的。 –