[英]Wasn't the Double Type precision of 15 digits in C#?
我正在測試Brainteasers的代碼:
double d1 = 1.000001;
double d2 = 0.000001;
Console.WriteLine((d1 - d2) == 1.0);
結果是“假的”。 當我更改數據類型時:
decimal d1 = 1.000001M;
decimal d2 = 0.000001M;
decimal d3 = d1-d2;
Console.WriteLine(d3 == 1);
該程序寫出正確的答案:“真”。
此問題僅在浮點后使用6位數。 15位數的精度怎么樣?
這與精度無關 - 它與表示性舍入誤差有關。
System.Decimal
能夠表示大浮點數,並且可以顯着降低發生任何舍入錯誤的風險,例如您所看到的錯誤。 System.Single
和System.Double
不具備此功能,並將關閉這些數字並創建類似於您在示例中看到的問題。
System.Decimal
使用縮放因子來保存小數位的位置,從而允許精確表示給定的浮點數,而System.Single
和System.Double
只能盡可能接近您的值。
有關詳細信息,請參閱System.Double
:
請記住,浮點數只能近似一個十進制數,並且浮點數的精度決定了該數字近似於十進制數的准確程度。 默認情況下,Double值包含15個十進制數字的精度,但內部最多保留17位數。 浮點數的精度有幾個結果:
對於特定精度看起來相等的兩個浮點數可能不相等,因為它們的最低有效位數不同。
如果使用十進制數,使用浮點數的數學或比較操作可能不會產生相同的結果,因為浮點數可能不完全接近十進制數。
通常,檢查浮點值是否相等的方法是檢查near -equality,即檢查接近該數據類型的最小值(稱為epsilon )的差異。 例如,
if (Math.Abs(d1 - d2) <= Double.Epsilon) ...
這測試以查看d1
和d2
是否由相同的位模式表示給出或取最低有效位。
更正 (2015年3月2日新增)
經過進一步檢查,代碼應該更像這樣:
// Assumes that d1 and d2 are not both zero
if (Math.Abs(d1 - d2) / Math.Max(Math.Abs(d1), Math.Abs(d2)) <= Double.Epsilon) ...
換句話說,取d1
和d2
之間的絕對差值,然后將其除以d1
和d2
的最大值, 然后將其與Epsilon
進行比較。
參考
• http://msdn.microsoft.com/en-us/library/system.double.epsilon.aspx
• http://msdn.microsoft.com/en-us/library/system.double.aspx#Precision
十進制類型實現十進制浮點,而double是二進制浮點。
十進制的優點是它在舍入方面表現得像人類一樣,如果用十進制值初始化它,那么該值將按照您指定的方式精確存儲。 這僅適用於有限長度的十進制數,並且在可表示的范圍和精度內。 如果你用1.0M / 3.0M初始化它,那么就不會像在紙上寫0.33333一樣精確地存儲它。
如果初始化帶有小數的二進制FP值,它將從人類可讀的十進制形式轉換為很少完全相同的二進制表示。
十進制類型的主要目的是實現財務應用程序,在.NET實現中它也具有遠高於double的精度,但二進制FP直接由硬件支持,因此明顯快於十進制FP操作。
請注意,double精確到大約15 位有效數字,而不是15 位小數 。 d1初始化為7有效數字值而不是6,而d2僅有1有效數字。 它們具有顯着不同的幅度這一事實也無濟於事。
浮點數的想法是它們對於特定數量的數字並不精確。 如果您想要這種功能,您應該查看decimal
數據類型。
精度不是絕對的,因為不可能精確地在十進制和二進制數之間進行轉換。
在這種情況下,當以二進制表示時,.1十進制將永遠重復。 它轉換為.000110011001100110011 ...並永遠重復。 精確度不會精確存儲。
避免比較浮點數的相等性。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.