Reputation: 854
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
Upvotes: 1
Views: 170
Reputation: 98398
https://metacpan.org/pod/Math::BigInt#Arithmetic-methods : "These methods modify the invocand object and returns it." In other words, bmod
, bsub
, and badd
are like %=
, -=
, and +=
, not like %
, -
, and +
.
So everywhere where you call one of the arithmetic methods, you should copy first, so the object you are currently calling the method on isn't changed:
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
(Also changed your test to do modulus, not division.)
Upvotes: 6