Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does modulo operation gives different results in Java VS Perl?

Tags:

java

modulo

perl

I run this in Java 7 and I get:

double remainder1 = 1 % 1000;
double remainder2 = 0.01 % 1000;
double remainder3 = -1 % 1000;

System.out.println("START: "+remainder1+" | "+remainder2+" | "+remainder3);
>>>START: 1.0 | 0.01 | -1.0

But when I run the same operations in Perl 5.8.8 I get different results for two out of three:

my $remainder1 = 1 % 1000;
my $remainder2 = 0.01 % 1000;
my $remainder3 = -1 % 1000;
print "START: $remainder1 | $remainder2 | $remainder3";
>>>START: 1 | 0 | 999

Why is there such a difference in the last two calculations? How can I get perl to match java results?

like image 638
goe Avatar asked Nov 03 '16 14:11

goe


People also ask

How does modulo operator work in Java?

Modulo or Remainder Operator returns the remainder of the two numbers after division. If you are provided with two numbers, say A and B, A is the dividend and B is the divisor, A mod B is there a remainder of the division of A and B. Modulo operator is an arithmetical operator which is denoted by %.

How to write modulus in Java?

If both operands for %, the modulus operator have type int, then exprleft % exprright evaluates to the integer remainder. For example, 8 % 3 evaluates to 2 because 8 divided by 3 has a remainder of 2.

How does modulo work with negative numbers in Java?

If we have negative numbers and use the % operator on them, we will get the result dependent on the left operand's sign. If we have the left operand as positive, we will get the result as positive, and if the left operand is negative, we will get the result as negative.

Is modulo faster than if?

A modulo-operation is very slow. An if is most likely to be faster than a modulo and more readable.


2 Answers

The second case:

  • % operates on integers and floating-point numbers in Java,
  • % only operates on integers in Perl.

The third case:

  • Java defines the modulus operation such that the following equation is true:

    dividend == ((int)(dividend/divisor)) * divisor + (dividend % divisor)
    
    e.g. -1 = 0 * 1000 + -1
    
  • Perl defines the modulus operation such that the following equation is true:

    $dividend == floor($dividend/$divisor) * divisor + ($dividend % $divisor)
    
    e.g. -1 = -1 * 1000 + 999
    

The Perl way has the advantage that the quotient (floor($dividend/$divisor)) will always have the same sign as the dividend.


To get the same behaviour as Java in Perl, use the POSIX::fmod function.

This is identical to the C function fmod().

$r = fmod($x, $y);

It returns the remainder $r = $x - $n*$y, where $n = trunc($x/$y). The $r has the same sign as $x and magnitude (absolute value) less than the magnitude of $y.

use POSIX 'fmod';

$m1 = fmod(1, 1000);     # 1
$m2 = fmod(0.01, 1000);  # 0.01
$m3 = fmod(-1, 1000);    # -1
like image 128
mob Avatar answered Oct 11 '22 22:10

mob


The Java modulo operator can work with floating point types and also has the property that the result will be negative if the first argument is negative.

The Perl modulo operator is for integer types only and the result is always positive.

If you want the Perl one to behave like the Java one, then scale the fractions up to integers with an appropriate multiplication, take the modulus, and then divide to get the final result. Compensate for the negative sign manually. Although you might be better off building your own version of the operator yourself.

like image 28
Bathsheba Avatar answered Oct 12 '22 00:10

Bathsheba