5

我正在尝试以浮点数进行扫描: 13.8518009935297 。第一个例程是我自己的,第二个是 MacOSX libc 的 strtod,第三个是 GMP 的 mpf_get_d(),第四个是 perls numeric.c:Perl_my_atof2()。

我使用这个片段来打印尾数:

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 的二进制文件放在一起时,我得到的值是不同的。

4

1 回答 1

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 相同的结果。不同之处在于您在附录中指出的错误。

于 2013-08-19T12:00:07.663 回答