•Re: Best way to make sure a number is an even multiple of another?
by merlyn (Sage) on Oct 21, 2004 at 13:08 UTC
|
sub fix {
my $n = shift; # must be greater or equal to this (assert >= 0)
my $m = shift; # must be multiple of this (assert > 0)
$m*int(($n+$m-1)/$m);
}
| [reply] [d/l] |
|
|
| [reply] |
|
|
| [reply] [d/l] |
|
|
|
|
|
Re: Best way to make sure a number is an even multiple of another?
by castaway (Parson) on Oct 21, 2004 at 12:58 UTC
|
sub fix{
my ($n,$m)=@_;
my $M = $n % $m;
$M && return $n + $m - $M;
$n;
}
C. | [reply] [d/l] |
Re: Best way to make sure a number is an even multiple of another?
by itub (Priest) on Oct 21, 2004 at 13:00 UTC
|
use POSIX qw(ceil);
sub fix {
my ($n, $m) = @_;
ceil($n/$m)*$m;
}
| [reply] [d/l] |
Re: Best way to make sure a number is an even multiple of another?
by Corion (Patriarch) on Oct 21, 2004 at 13:22 UTC
|
For the fun of it, I wanted to give the thing a closed, whole-integer form. The problem was, that a "close fitting" was wanted, and all I had was the following expression:
my $M;
my $n;
my $remaining = $n % $M;
my $next_multiple = $n + $M - $remaining;
This means, that my calculation always was one multiple too large whenever $remaining was zero. So I needed to fudge that a bit, by the idea that, if I made $n one smaller in one part, and added that one later on, I could maybe shift the error into the right direction:
for my $n (1..20) {
print "$n:\t";
for my $M (2..5) {
my $remaining = ($n-1) % $M; # subtract one from the remainder
my $next_multiple = $n-1 + $M - $remaining;
print "$next_multiple\t";
};
print "\n";
};
or, as my unreadable shell test expression:
perl -e "my $n=20; for(@ARGV){$x=$n-1+($_-($n-1)%$_);print qq($n\[$_]
+:$x\n)}" 2 3 4 5 6 7 8 9 10
# resp.
$x=$n-1+($M-($n-1)%$M)
| [reply] [d/l] [select] |
Re: Best way to make sure a number is an even multiple of another?
by bart (Canon) on Oct 21, 2004 at 13:20 UTC
|
sub fix {
my($n, $m) = @_;
$n + ($n*$m - $n)%$m;
}
| [reply] [d/l] |
|
|
| [reply] |
|
|
I don't trust modulo on a negative number. I'm never sure what value -2 % 5 will have. 3 or -2? I believe it depends on the language.
So, I want an easy, reliable way to add a multiple ($i) of $m so that $i - $n >= 0. The exact number doesn't matter, as
($r*$m + $s) % $m == $s % $m
for any non-negative integers $r and $s, and positive integer $m.
$m*$n is both a multiple of $m, and at least as large as $n. | [reply] [d/l] [select] |
|
|
|
|
Re: Best way to make sure a number is an even multiple of another?
by Limbic~Region (Chancellor) on Oct 21, 2004 at 13:04 UTC
|
demerphq,
I am not sure how large your numbers are, so the following approach may not be what you need/want:
- Perform prime factorization on the number
Math::Big::Factors or factors if the numbers are smaller than 2^32
- Look through all combinations (multiplying factors) until you find one that meets your criteria
If I get a chance, I might even try and implementation.
| [reply] |
|
|
| [reply] |
|
|
demerphq,
I am guilty. I am guilty of not spending enough time reading your question to see what you were asking for before jumping to conclusions. The conclusion I jumped to is that you wanted the largest factor greater than or equal to a certain number. To that end, here is code that I believe does that.
While I know that this isn't what you asked for, it might be of benefit to someone.
| [reply] [d/l] |
Re: Best way to make sure a number is an even multiple of another?
by Roy Johnson (Monsignor) on Oct 21, 2004 at 13:50 UTC
|
sub fix2 {
my $n = shift; # must be greater or equal to this (assert >= 0)
my $m = shift; # must be multiple of this (assert > 0)
$n + ($m-$n)%$m;
}
Caution: Contents may have been coded under pressure.
| [reply] [d/l] |
Re: Best way to make sure a number is an even multiple of another?
by thospel (Hermit) on Oct 21, 2004 at 16:20 UTC
|
Assuming $n is any integer and $m is a positive integer (if $m is negative it finds the first equal or below instead of equal or above)
-$n%$m+$n
(don't use this under "use integer") | [reply] [d/l] |
Re: Best way to make sure a number is an even multiple of another?
by TomDLux (Vicar) on Oct 21, 2004 at 14:55 UTC
|
M goes into N int( N/M ) times, with a remainder of M%N.
So, M * (1 + int( N/M )) will be the
smallest multiple of M greater then N.
--
TTTATCGGTCGTTATATAGATGTTTGCA
| [reply] |
|
|
The trick is that what the OP wanted was greater than or equal to, without doing an if (or equivalent). Here's one way to modify your suggestion:
$m*(($n%$m > 0) + int($n/$m));
Caution: Contents may have been coded under pressure.
| [reply] [d/l] |