首页 > 解决方案 > Why does Math::BigInt has wrong output?

问题描述

I need to get the nearest number $new to $orig divisible by $divisor. The $new should be greater than $orig. So I have come with the following formula (hopefully, there is no error in it):

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

Now, the $orig number is an integer and has up to 30 digits. I want to implement this into a Perl function using Math::BigInt, but the output is quite wrong.

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

标签: perlbigint

解决方案


https://metacpan.org/pod/Math::BigInt#Arithmetic-methods:“这些方法修改调用对象并返回它。” 换句话说,bmodbsub, 和, , , 和,,,和,不badd一样%=-=+=%-+

因此,在您调用其中一种算术方法的任何地方,您都应该先复制,这样您当前调用该方法的对象就不会改变:

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

(还将您的测试更改为模数,而不是除法。)


推荐阅读