views:

4196

answers:

3

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 and mod. However, what I don't understand is what effect the sign of each argument should have on the result. Wouldn't the div always be positive, being the number of times n2 fits into n1? How's the arithmetic supposed to work in this situation?

+7  A: 

Given that a = qd + r , the arithematic says that for negative numbers , there is an ambiguity when calculating the remainder: For ex :

the division of −42 by −5 can be expressed as either

−42 = 9×(−5) + 3 as is usual for mathematicians, or

−42 = 8×(−5) + (−2). So the remainder is then either 3 or −2.

More info here

Also , the output in case of -ve numbers in mod / div is implementation dependent in software languages. More info here (look at the table on right)

Learning
+1  A: 

It might be helpful to have a look at another question on stackoverflow that was asked recently: http://stackoverflow.com/questions/450410/why-is-modulus-different-in-different-programming-languages

innaM
Well, I was the one who asked that question, as it happens. And the initial question was in the context of integers rather than floats.
boost
Ouch! Sorry then. Hopefully, somebody else might be interested.
innaM
+3  A: 

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
ysth
fmod, eh? I stand corrected. Thanks very much for pointing that out.
boost