我在想,爲什麼我的簡單增加了一些雙值導致的Java下面的結果非常小的雙精度值(JAVA)的:加
double a = 1 + 1E-10; // 1.0000000001 (as expected)
double b = 1 + 1E-15; // 1.000000000000001 (as expected)
double c = 1 + 1E-20; // 1.0 (why?)
我想我至少可以加雙值.MIN_VALUE,似乎是4.9E-324。
我在這裏做錯了什麼?
我在想,爲什麼我的簡單增加了一些雙值導致的Java下面的結果非常小的雙精度值(JAVA)的:加
double a = 1 + 1E-10; // 1.0000000001 (as expected)
double b = 1 + 1E-15; // 1.000000000000001 (as expected)
double c = 1 + 1E-20; // 1.0 (why?)
我想我至少可以加雙值.MIN_VALUE,似乎是4.9E-324。
我在這裏做錯了什麼?
As @ Turing85指出,double
有11位指數和53位尾數。
我們在這裏計算的是1.0 + 1E-20。爲了表示該數字(比1.0更精確),我們需要至少21位十進制數字的精度或71位。這比尾數中提供的double
更精確。
所以,最近的可表示爲double
號碼爲1.0 + 1E-20是...... 1.0。這就是你得到的結果。
歡迎來到神祕的浮點運算世界。
你在這裏沒有做錯什麼。小數精度的概念就在眼前。浮點數總是有可能出錯。 和公共誤差值被表示爲:
- 1/2E-n <= error <= 1/2E-n
其中n是已定義的小數的位數。
有關浮點錯誤的更多信息,請參閱here。
「我在這裏做錯了什麼?」 - 你忘記了任何浮點數表示所具有的精度問題。 – Thomas
爲了增強技術性:在[IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point)中,有11位指數和53位尾數。指數定義數字的大小順序,而尾數定義數字值。例如,在'2.63 x 10^3'中,'2.63'是數值,而'3'是數值。如果添加兩個數值差別很大的值,則可能會遇到問題。精確度,這是你觀察到的。一般來說,當(大多數)分量大致相同或大致相同時,「float」和「double」運作良好。 – Turing85
謝謝@ Turing85,但我仍然不明白,爲什麼我可以使用'Double.MIN_VALUE'來描述一個非常小的值,但不能按預期使用它。 :P是否僅僅因爲其他值(在這種情況下爲1)具有非常不同的幅度? – Thomas