Как избежать генерации очень маленькой вычислительной ошибки в perl - PullRequest
1 голос
/ 28 апреля 2020
my $a = 243300;
my $b = 3000;
my $c = 81.10;

if (($a - $b * $c) != 0) {
    warn "delta is " . ($a - $b * $c);
} else {
    print "OK\n";
}

Результат дает очень маленькую разницу:

Mac: ~ # perl f.pl
delta is 2.91038304567337e-11 at f.pl line 6.

Я могу обойти, сравнив с 0,01, но как избежать такой проблемы и как получается очень маленькая разница?

1 Ответ

3 голосов
/ 28 апреля 2020

Вы можете использовать числовой пакет произвольной точности, например Math::BigRat, Math::BigFloat или Math::Decimal, но это будет значительное снижение производительности.

use Math::Decimal qw(dec_sub dec_mul);
my ($a,$b,$c,$delta);
$a = 243300;
$b = 3000;
$c = 81.10;
$delta = dec_sub($a, dec_mul($b,$c));
if ($delta != 0) {
    warn "delta [M::D]is $delta\n";
} else {
    print "OK [M::D]\n";
}

use Math::BigRat;
$a = Math::BigRat->new(243300);
$b = Math::BigRat->new(3000);
$c = Math::BigRat->new(81.10);
$delta = $a - $b * $c;
if ($delta != 0) {
    warn "delta [M::BR]is $delta\n";
} else {
    print "OK [M::BR]\n";
}
...