2013-07-30 23 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。不同之处在于你在附件中指出的错误。