2010-01-17 26 views
0

可能重複:
Why is floating point arithmetic in C# imprecise?
Why does ghci say that 1.1 + 1.1 + 1.1 > 3.3 is True?爲什麼我在Perl中從自身中減去相同的浮點數時得不到零?

#!/usr/bin/perl 
$l1 = "0+0.590580+0.583742+0.579787+0.564928+0.504538+0.459805+0.433273+0.384211+0.3035810"; 
$l2 = "0+0.590580+0.583742+0.579788+0.564928+0.504538+0.459805+0.433272+0.384211+0.3035810"; 
$val1 = eval ($l1); 
$val2 = eval ($l2); 
$diff = (($val1 - $val2)/$val1)*100; 
print " (($val1 - $val2)/$val1)*100 ==> $diff\n"; 

令人驚訝的輸出最終是

((4.404445 - 4.404445)/4.404445)*100 ==> -2.01655014354845e-14. 

難道不應該是零???? 請問任何人都可以這樣解釋......

+2

什麼,你不覺得0.000000000000201655014354845是接近零? – Ether 2010-01-17 17:50:38

+0

這個問題並不完全是引用的非perl問題的重複,因爲問題很複雜,因爲perl提供的默認字符串化精度略低於可用的數字精度。 – ysth 2010-01-18 06:39:24

回答

7

它非常接近零,這正是我所期望的。

爲什麼它應該是零? 0.579787!= 0.579788和0.433273!= 0.433272。很可能沒有一個具有精確的浮點表示,因此您應該期望一些不準確的地方。

3

當您將兩個字符串更改爲相等(在$l1$l2之間有兩個不同數字)時,它確實會導致零。

它演示的是您可以創建2個不同的浮點數($val1$val2),它們在打印時看起來相同,但在內部有微小差異。如果你不小心,這些差異可以放大。

Vinko Vrsalovic發佈了一些很好的鏈接來解釋原因。

4

perlfaq4的答案Why am I getting long decimals (eg, 19.9499999999999) instead of the numbers I should be getting (eg, 19.95)?


內部,您的計算機代表浮點二進制數。數字(如兩個冪)計算機不能完全存儲所有數字。一些實際數字在這個過程中失去了精確性這是計算機如何存儲數字並影響所有計算機語言的問題,而不僅僅是Perl。

perlnumber顯示數字表示和轉換的血淋淋的細節。

要限制數字中的小數位數,可以使用printf或sprintf函數。有關更多詳細信息,請參閱「浮點運算」。

printf "%.2f", 10/3; 

my $number = sprintf "%.2f", 10/3; 
+0

這是perlfaq的另一面;看到我對這個問題的評論。 – ysth 2010-01-18 06:43:33

相關問題