2013-07-30 4 views
5

Я пытаюсь сканировать поплавок: 13.8518009935297. Первая рутина - моя, вторая - MacOSX libc's strtod, третья - mpf_get_d() GMP, четвертая - perls numeric.c: Perl_my_atof2().Perl mantissa отличается от других двухместных номеров

Я использую этот фрагмент кода для печати мантиссы:

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 

Разница между первыми тремя функциями имеет закругление. Однако мантисса перла совсем не синхронизирована.

Если я снова напечатаю все четыре двойника на строку, я получаю одну и ту же десятичную двойную спину, цифры, похоже, равны.

Мой вопрос: Разница между my-func, strtod, GMP округляется. Тем не менее, почему мантисса perl так сильно не синхронизирована, но все же, если преобразован обратно в десятичную, он снова становится таким же числом. Разница равна 22, поэтому следует отметить в десятичной дроби . Как я могу это объяснить?

Append: К сожалению, я думаю, что я понял, проблема:

$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. Разница была ошибкой, которую вы указали в append.

Смежные вопросы