2013-07-30 65 views
5

我試圖在float中掃描:13.8518009935297。第一個例程是我自己的,第二個是MacOSX libc的 strtod,第三個是GMP的mpf_get_d(),第四個是perls numeric.c:Perl_my_atof2()。Perl尾數與其他雙打不同

我用這個片段打印尾數:

union ieee_double { 
     struct { 
       uint32_t fracl; 
       uint32_t frach:20; 
       uint32_t exp:11; 
       uint32_t sign:1; 
     } s; 
     double d; 
     uint64_t l; 
}; 

union ieee_double l0; 
l0.d = .... 
printf("... 0x%x 0x%x\n", l0.s.frach, l0.s.fracl); 

四個函數的返回值是:

my-func : 0xbb41f 0x4283d21b 
strtod : 0xbb41f 0x4283d21c 
GMP  : 0xbb41f 0x4283d21b 
perl : 0xbb41f 0x4283d232 

前三項功能之間的差異四捨五入。 但是perl的尾數是非常不同步的。

如果我再次打印所有四個雙打到一個字符串我得到 相同的小數雙回,數字似乎是相等的。

我的問題: my-func,strtod,GMP的區別在於四捨五入。然而, 爲什麼perl的尾數非同步,但仍然,如果 轉換回十進制,它會再次結束爲相同的數字。 所不同的是22,所以應該注意小數點 分數。我怎樣才能解釋這一點?

附加: 對不起,我想我想通了這個問題:

$r = rand(25); 
    $t = $p->tokenize_str("$r"); 

tokenize_str()是我從執行字符串轉換爲雙的。 但是,perl stringify「$ r」輸出$ r爲13.8518009935297,這是已經截斷的 。 $ r的實際值是不同的,所以當我在最後的時候得到 $ t和$ r的二進制文件,我得到的值有差異。

+2

根據[本頁](http://babbage.cs.qc.cuny.edu/IEEE-754.old/64bit.html),該尾數實際上有兩位數的小數精度,比您顯示的要多:'13.851800993529700 '。 Perl版本等於'13.851800993529740'。所以這種差異在你的精確度上並不重要。不過,爲什麼Perl不同,這是一個有趣的問題。 –

+0

對不起,找出錯誤(參見上文)。無論如何感謝您的答案... –

回答

0

下面是一些Perl代碼來回答你的問題:

perl -le '($frac1, $frach)=unpack("II", pack "d", .0+"13.8518009935297"); 
print sprintf("%d %d 0x%03x 0x%04x", ($frach >> 31)&1, ($frach>>20)&0x5ff, $frach & 0xfffff, $frac1)' 

- > 0 1026 0xbb41f 0x4283d21c

Perl中給出了相同的結果的strtod。不同之處在於你在附件中指出的錯誤。