2014-03-06 107 views
2

我對此很困惑。這是我遇到的。內部perl和內部shell之間的浮點計算差異

我寫了一個perl代碼來計算兩個數的差值,並根據差值是否大於0.5來決定是否打印該行。

爲了給出一個玩具例如:

a 0.9 0.4 
b 0.8 0.2 
c 0.7 0.3 
d 0.81 0.3 
e 0.79 0.3 

所以代碼應該打印出線路A,B,d但不C,E。我試圖這樣做的方法有兩種:

1.Directly測試,如果差大於或等於0.5,如果是這樣,打印:

chomp; 
my @array = split/\t/; 
my $diff = $array[1] - $array[2]; 
if ($diff >=0.5) { 
    print $_; 
} 

2.輸出差分第一成一個文件,然後用awk來選擇:

print $_,"\t",$diff,"\n"; 

Then with awk: 
awk '{ if ($NF >= 0.5) print}' file 

我很驚訝地發現,這兩種方式產生了我的實際文件兩種不同的結果(萬行)。 awk的方式給了稍微更多的結果。我查看了兩個輸出的不同之處,並且似乎使用perl方式(1)錯過了一些行。

有誰知道這是爲什麼?在perl中進行這種計算和條件測試有什麼問題嗎?

+2

對於啓示:'printf「%.20f」,$ diff' – mob

+0

@mob會這樣做的結果是否一樣?如果是這樣,爲什麼?它背後的理論是什麼? – olala

+3

@ user2157668這不會修復這個錯誤,但它會幫助你理解問題:'printf'%.20f \ n「,0.7-0.3'輸出'0.39999999999999996669'而不是'0.4',因爲不是所有的實數具有精確的二進制表示形式,就像'1/3'沒有精確的(和有限大小)十進制表示形式:'0.3333 ...'。 – amon

回答

1

你可能想看看Math::BigFloat Perl模塊,看看有關精度的方法。你可以提供perl腳本和awk腳本之間不同結果的幾行代碼的輸入值嗎?