2013-07-30 8 views
5

私はフロートでスキャンしようとしています:13.8518009935297。 最初のルーチンは私のもので、2番目はMacOSX libcの strtod、3番目のものはGMPのmpf_get_d()で、 perls numeric.c:Perl_my_atof2()です。 4つの機能のために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の仮数は全く同期していません。

文字列に4つの倍精度文字をすべて再度印刷すると、同じ小数点以下2桁も戻ってくるので、数字は等しいようです。

私の質問: my-func、strtod、GMPの違いは四捨五入です。しかし、 なぜperlの仮数はあまり同期していませんが、それでもなお が10進数に変換された場合、それは再び同じ数値として終了します。 違いは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)によれば、その仮数は実際に表示するよりも2桁多い10進精度を持っています: '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と同じ結果になります。違いはあなたが追加で示した間違いでした。

関連する問題