How do you calculate div and mod of floating point numbers?
Solution 1
Given a = qd + r
, there is an ambiguity when calculating the remainder for negative values of d
.
E.g.:
The expression −42 ÷ −5
, can be expressed as either as:
−42 = 9×(−5) + 3
or −42 = 8×(−5) + (−2)
.
So the remainder is then either 3 or −2.
For more info: Wikipedia:Remainder "Inequality satisfied by the remainder"
Also, the output in case of negative numbers in mod / div is implementation dependent in software languages. See Wikipedia: Modulo operation (look at the table on right)
Solution 2
The title asks one question, the body another. To answer the title question, just as in C, the % operator is an integer modulus, but there's a library routine "fmod" that's a floating point modulus.
use POSIX "fmod";
sub foo {
my $n1 = shift;
my $n2 = shift;
print "perl's fmod=" . fmod($n1,$n2), "\n";
my $res = $n1 / $n2;
my $t = int($res);
print "my div=$t", "\n";
$res = $res - $t;
$res = $res * $n2;
print "my mod=" . $res . "\n\n";
}
foo( 3044.952963, 7.1 );
foo( 3044.952963, -7.1 );
foo( -3044.952963, 7.1 );
foo( -3044.952963, -7.1 );
gives
perl's fmod=6.15296300000033
my div=428
my mod=6.15296300000033
perl's fmod=6.15296300000033
my div=-428
my mod=6.15296300000033
perl's fmod=-6.15296300000033
my div=-428
my mod=-6.15296300000033
perl's fmod=-6.15296300000033
my div=428
my mod=-6.15296300000033
bugmagnet
Software Engineer. Over 20 years experience in user-support and programming. Working full-time as Software Engineer for Daisy Digital. Research assistant / librarian for, and contributor to, the History of Programming Languages (HOPL).
Updated on July 05, 2022Comments
-
bugmagnet almost 2 years
In Perl, the
%
operator seems to assume integers. For instance:sub foo { my $n1 = shift; my $n2 = shift; print "perl's mod=" . $n1 % $n2, "\n"; my $res = $n1 / $n2; my $t = int($res); print "my div=$t", "\n"; $res = $res - $t; $res = $res * $n2; print "my mod=" . $res . "\n\n"; } foo( 3044.952963, 7.1 ); foo( 3044.952963, -7.1 ); foo( -3044.952963, 7.1 ); foo( -3044.952963, -7.1 );
gives
perl's mod=6 my div=428 my mod=6.15296300000033 perl's mod=-1 my div=-428 my mod=6.15296300000033 perl's mod=1 my div=-428 my mod=-6.15296300000033 perl's mod=-6 my div=428 my mod=-6.15296300000033
Now as you can see, I've come up with a "solution" already for calculating
div
andmod
. However, what I don't understand is what effect the sign of each argument should have on the result. Wouldn't thediv
always be positive, being the number of timesn2
fits inton1
? How's the arithmetic supposed to work in this situation? -
bugmagnet about 15 yearsfmod, eh? I stand corrected. Thanks very much for pointing that out.
-
Flimm almost 10 yearsDoes anyone know of an alternative such that
fmod(-23, 10)
returns7
instead of-3
? -
ysth almost 10 yearsjust add 10 if it's less than 0?
-
Flimm almost 10 years@ysth: that's what I ended up doing, but it would be nice if there was a module somewhere that did this already so I didn't have to include too many helper functions in my code.
-
mctylr almost 10 yearsFor the mathematical background, see modular arithmetic and/or abstract (or elementary) algebra.