2017-05-12 45 views
2

這是俗稱,它是不安全的雙重價值與==操作符比較鑄造小數。在這個例子中返回false:它是安全的比較從雙打

double d1 = 0.11; 
double d2 = 0.44 - 0.33; 
Console.WriteLine(d1 == d2); 

但是,如果我們投數值爲十進制,它返回true:

double d1 = 0.11; 
double d2 = 0.44 - 0.33; 
Console.WriteLine((decimal)d1 == (decimal)d2); 

是否總是安全的,比較從雙鑄造小數,還是有一些情況哪裏可以給人意想不到的結

更新: 侯賽因的例子是不錯的,它表明,它可能會被錯誤事實。但是我更感興趣的是看看是否有相反的例子,當我們期望十進制值是相等的,而不是。甚至更廣泛的是,當我們從兩倍變爲十進制時發生了什麼。

+0

可能重複[要比較雙倍和小數,我應該將double轉換爲小數還是將decimal轉換爲double?](http://stackoverflow.com/questions/10612207/to-compare-double-and-decimal - 應該我投 - 雙十進制或十進制到雙倍) – Alexander

+0

@Alexander不,我在問我的問題之前看過這個問題。我的問題完全不同。 –

+0

在該主題中有答案,該主題描述了這種轉換是可能的,而不會影響準確性。 – Alexander

回答

0

它總是安全的,提供你知道浮點和小數類型,之間的轉換語義認識上實現代碼的影響。

這就是說,除非你有一個很好的理由投,你是更安全的檢查之後一段給定公差平等的標準方法。 (例如(0.999 - 1.00) < 0.01。)

Explicit Numeric Conversions Table (C# Reference)

  • 當轉換浮點或雙精度到十進制,源值是 第28小數點後轉換爲十進制表示並圓整到最接近的數字 如果需要的話。取決於 源的值的值,可能會發生以下結果之一:

    • 如果源值太小而不能表示爲小數,所述 結果變爲零。

    • 如果源值是NaN(不是數字),無窮大或太大以致 被表示爲小數,則會引發OverflowException。

    • 當您將小數轉換爲浮點或雙精度時,十進制值爲 舍入爲最接近的雙精度值或浮點值。

1

在這種情況下,你可能會得到期望的結果,但通常你的答案是NO 。 當您在中存儲值時,將其轉換爲十進制不會提高其精度(link)。

考慮下面的例子。平等返回true,但我們期望錯誤。

double myDouble1 = 0.11; 
double myDouble2 = 0.10999999999999999; 
Console.WriteLine((decimal)myDouble1 == (decimal)myDouble2); //true, but we expect false 

但是,如果你保存了這些值小數,那麼你會得到正確的結果。

decimal myDecimal1 = 0.11M; 
decimal myDecimal2 = 0.10999999999999999M; 
Console.WriteLine(myDecimal1 == myDecimal2); //false 
+0

同意.......... –

+1

您爲什麼認爲目標是提高精度? OP沒有提到提高精確度。比較時,我們通常希望降低精度,而不是增強它。 –

+0

在Alex的例子中,我假設他正在尋求提高精度 –

-1

double店近似值,因此這種情況下將不等於:

double d1 = 0.11; 
double d2 = 0.44 - 0.33; 
Console.WriteLine(d1 == d2); 

decimal專賣店值更接近它們是什麼不是做了double所以這將是平等的:

Console.WriteLine((decimal)d1 == (decimal)d2); 

但重要的是要指出,即使decimal是一個近似值。例如,您無法使用小數存儲Pi的確切值。

衆所周知,比較.net中的double值是不安全的。

這一切都取決於您的計算所需的精度水平。對於一些計算來說,使用它是很好的,對於其他的則不然。

System.Doubledouble in C#)and System.Singlefloat in C#)被存儲爲近似值。例如:

double x = 0.1d; 

x將存儲與該值最接近的可用雙精度值。


重要界限

這是要注意的是不像double,一個decimal不會將自身存儲的標準化,但它會記住零點非常重要的。例如,嘗試以下代碼:

decimal dec1 = 1.000000000m; 
double dbl11 = 1.000000000; 

Console.WriteLine(dec1); // outputs: 1.000000000 (remembers all 9 zeros) 
Console.WriteLine(dbl11); // outputs: 1 

<==Try Me==>

decimal被存儲爲在存儲器中,但是doublefloat基座10被存儲在基部2他們都有以下組件:一個尾數,指數和符號。例如:

44.5可以在「十進制浮點」爲尾數4.45爲1的指數來表示,而4450將具有相同的尾數但3

指數你可以閱讀如果有興趣,請致電Floating PointsDecimals


類題外話,但有趣的問題的

我是說某人小數和近似等。他們提出了這個問題:想象一下,你擁有一家商店,你以$ 1.00購買3件商品。你甚至想削減哪些客戶不得不承擔額外的費用並支付額外的費用?

+2

「'雙'存儲近似值」 - 不,「double」*存儲*一個非常精確的值。許多算術運算(包括從源代碼中的小數轉換)將失去信息以產生「雙」,但其值本身是精確的。 –

+0

那麼第一種情況怎麼不等於?對不起,明天回覆,以防您回覆 - 它已經晚了,需要睡覺:) – CodingYoshi

+2

因爲存儲的值不同 - 它們*正好* 0.11000000000000000055511151231257827021181583404541015625和0.10999999999999998667732370449812151491641998291015625。當執行從源代碼中的十進制表示到'double'的轉換時,可能再次執行相減,但是'double'值本身並不是近似值。這就像談論'int' - 如果你寫'int x =(int)10.6;'那麼它將存儲值10.轉換中的信息丟失,但值恰好爲10. –

2

衆所周知,比較.net中的double值是不安全的。在這個例子中,它返回錯誤

你誤解了什麼是不安全的。

假設任意十進制表示法(即使它很短(用十進制寫))完全用二進制浮點表示是不安全的。假設-在二進制浮點值之間產生除數學結果的最近可表示的浮點值以外的任何東西(特別是假定它總是產生數學結果並不安全),這並不安全。

d1 == d2是完全安全的,所以是(decimal)d1 == (decimal)d2。第一個不會總是返回你想要的東西,但第二個既不會返回,因爲它沒有理由按照上述原則。一旦d1d2已計算,近似值已經完成:

  • 表示近似值,因爲你似乎認爲,0.11應該是數學值100分之11,它不是,它是最接近的可表示值;
  • 操作近似,因爲0.44減去0.33的數學結果可能無法準確表示,在這種情況下,將使用最接近的可表示值。

,這些近似值化合物和,加入在C#轉換爲decimal的第三近似值時,導致預期中的值的事實是巧合。如果任何事情都應該被普遍瞭解,應該是它已經發生後再修正一個近似,爲時已晚,並且增加另一個近似不會真正起作用。請參閱本文中的第一個示例Excel,這是Microsoft提供的另一款可編程產品。