PERL: неправильные вычисления с плавающей точкой
------------------------------
#!/usr/bin/perl
$a = 601; foreach $b (0..9) { $c = $a + $b / 10; print "$c: " . (($c * 100) - ($c * 10 * 10)) . "\n"; }
------------------------------
Выдает:
601: 0
601.1: 0
601.2: 7.27595761418343e-12
601.3: -7.27595761418343e-12
601.4: 0
601.5: 0
601.6: 0
601.7: 7.27595761418343e-12
601.8: -7.27595761418343e-12
601.9: 0
Вопрос:
Почему???
Проверялось на разных машинах с конфигурациями:
Perl 5.8.8/FreeBSD 7.0;
Perl 5.8.8/Linux gentoo (kernel 2.6.20-gentoo-r8);
Perl 5.8.8/Linux gentoo (kernel 2.4.32-gentoo-r7);
Perl 5.10.0/Linux Ubuntu 8.10 (kernel2.6.27-12-generic);
------------------------------
#!/usr/bin/perl
$a = 601; foreach $b (0..9) { $c = $a + [COLOR=Red]$b / 10[/COLOR]; print "$c: " . (($c * 100) - ($c * 10 * 10)) . "\n"; }
------------------------------
Это целочисленная операция так как $b - целое число, результатом его будет честный целочисленный ноль.
Дальнейшие вычисления дают если не 0, то предельно близкое к нему число.
Попробуйте заменить на $b / 10.0, увидите, что все встанет на свои места.
Дальнейшие вычисления дают если не 0, то предельно близкое к нему число.
Попробуйте заменить на $b / 10.0, увидите, что все встанет на свои места.
Попробовал:
$a = 601; foreach $b (0..9) { $c = $a + $b / 10.0; print "$c: " . (($c * 100) - ($c * 10 * 10)) . "\n"; }
601: 0
601.1: 0
601.2: 7.27595761418343e-12
601.3: -7.27595761418343e-12
601.4: 0
601.5: 0
601.6: 0
601.7: 7.27595761418343e-12
601.8: -7.27595761418343e-12
601.9: 0
Не помогло.
Насколько я знаю, perl не использует int для хранения чисел.
Для чисел используется signed long double.
Буду рад мыслям на эту тему.
Просьба внимательно прочиать вопрос и/или попробовать сию конструкцию у себя.
Вопрос весьма нетривиальный.
Вас смущают числа типа 7.27595761418343e-12 ?
Это близкие к нулю значения.
Они будут в любом языке программирования, работающим с числами двойной точности.
В данном случае это может происходить из за того, что умножение сразу на 100 отличается от двух умножений на 10. Это связано с представлением вещественных чисел в памяти машины - определенная потеря точности неизбежна.
Спасибо за информацию)
http://rt.perl.org/rt3/Public/Bug/Display.html?id=63304
Проблему можно считать решенной )