Почему Math :: BigInt имеет неправильный вывод? - PullRequest
1 голос
/ 29 февраля 2020

Мне нужно получить ближайшее число $new до $orig, делимое на $divisor. $new должно быть больше $orig. Итак, я пришел со следующей формулой (надеюсь, в ней нет ошибок):

$new = $orig + ($divisor - $orig % $divisor)

Теперь число $orig является целым числом и может содержать до 30 цифр. Я хочу реализовать это в Perl функции, используя Math::BigInt, но вывод совершенно неправильный.

use Math::BigInt;

Math::BigInt->accuracy(60);
Math::BigInt->precision(60);

my $orig = Math::BigInt->new('5967920747812842369477355441');  # A
my $divisor = Math::BigInt->new('719');                        # B
my $modulo = $orig->bmod($divisor);  # A % B = M
my $diff = $divisor->bsub($modulo);  # B - M = D
my $new = $orig->badd($diff);        # A + D = N
my $test = $new->bdiv($divisor);     # N / B = 0


print("orig : $orig\n");      # 10; should be: 5967920747812842369477355441
print("modulo : $modulo\n");  # 10; should be: 648
print("diff : $diff\n");      # 71; should be: 71
print("new : $new\n");        # 10; should be: 5967920747812842369477355512
print("test : $test\n");      # 10; should be: 0

1 Ответ

5 голосов
/ 29 февраля 2020

https://metacpan.org/pod/Math :: BigInt # Arithmeti c -методы : "Эти методы изменяют объект invocand и возвращают его." Другими словами, bmod, bsub и badd подобны %=, -= и +=, не похожи на %, - и +.

Поэтому везде, где вы вызываете один из методов арифметики c, вы должны сначала скопировать, чтобы объект, для которого вы в данный момент вызываете метод, не изменился:

use Math::BigInt;

Math::BigInt->accuracy(60);
Math::BigInt->precision(60);

my $orig = Math::BigInt->new('5967920747812842369477355441');  # A
my $divisor = Math::BigInt->new('719');                        # B
my $modulo = $orig->copy->bmod($divisor);  # A % B = M
my $diff = $divisor->copy->bsub($modulo);  # B - M = D
my $new = $orig->copy->badd($diff);        # A + D = N
my $test = $new->copy->bmod($divisor);     # N % B = 0


print("orig : $orig\n");      # 10; should be: 5967920747812842369477355441
print("modulo : $modulo\n");  # 10; should be: 648
print("diff : $diff\n");      # 71; should be: 71
print("new : $new\n");        # 10; should be: 5967920747812842369477355512
print("test : $test\n");      # 10; should be: 0

(Также изменился ваш тест делать модуль, а не деление.)

...