12

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?

mskfisher
  • 3,291
  • 4
  • 35
  • 48
bugmagnet
  • 7,631
  • 8
  • 69
  • 131

2 Answers2

17

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
  • 96,171
  • 6
  • 121
  • 214
  • fmod, eh? I stand corrected. Thanks very much for pointing that out. – bugmagnet Feb 01 '09 at 23:50
  • Does anyone know of an alternative such that `fmod(-23, 10)` returns `7` instead of `-3`? – Flimm May 29 '14 at 16:28
  • just add 10 if it's less than 0? – ysth May 29 '14 at 16:56
  • @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. – Flimm May 30 '14 at 09:36
8

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)

mctylr
  • 5,159
  • 20
  • 32
Learning
  • 8,029
  • 3
  • 35
  • 46
  • For the mathematical background, see [modular arithmetic](http://www.math.rutgers.edu/~erowland/modulararithmetic.html) and/or [abstract (or elementary) algebra](http://www.millersville.edu/~bikenaga/abstract-algebra-1/modular-arithmetic/modular-arithmetic.html). – mctylr Jul 24 '14 at 18:47