Я пытаюсь сканировать с плавающей запятой: 13.8518009935297. Первая подпрограмма — моя собственная, вторая — strtod из MacOSX libc, третья — mpf_get_d() из GMP, четвертая — 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 я получаю значения, которые расходятся.
13.851800993529700
. Версия Perl равна13.851800993529740
. Так что разница не существенна на вашем уровне точности. Тем не менее, это интересный вопрос, чем отличается Perl. - person Jim Garrison   schedule 30.07.2013