Notinlist
Notinlist

Reputation: 16640

Java modulo operator precedence

I need some help in debugging the following java program.

import java.util.Random;

public class NextInt
{
    public static void main(String[] args)
    {
        for(int i=0; i<20; ++i)
        {
            if(i>0)
                System.out.print(", ");
            int x = (new Random()).nextInt();
            System.out.print( x % 2 + 1);
        }
        System.out.println("");
    }
}

Will output (for example):

0, 1, 0, 1, 2, 2, 2, 0, 0, 1, 1, 1, 2, 0, 1, 1, 1, 1, 2, 1

I think the output should have been containing only ones and twos! If we think about the x % (2+1) interpretation then the output is correct. Is the modulo operator really weaker than the addition? Java tutorial says no. Or is there something else that I am missing?

Upvotes: 1

Views: 946

Answers (4)

nansen
nansen

Reputation: 2962

Guava's IntMath class offers an always positive modulo operation:

System.out.println(IntMath.mod(x, 2) +1); 

Upvotes: 1

Bert F
Bert F

Reputation: 87573

Note that

Random.nextInt()

may produce negative ints and that, in Java, the result of the remainder operator ('%') takes the sign of the left-hand operand. This differs amongst programming languages - see this table in the Wikipedia entry for Modulo for a sampling.

If you wanted just non-negative ints, use:

Random.nextInt(Integer.MAX_VALUE)

to produce ints between 0 (inclusive) and 2^31-1 (exclusive). Otherwise, if you wanted to handle the possible negative result of modulo and still get back just 1's or 2's, then use:

System.out.print(Math.abs(x % 2) + 1);

===

JavaDoc for Random.nextInt (emphasis is mine):

public int nextInt() Returns the next pseudorandom, uniformly distributed int value from this random number generator's sequence. The general contract of nextInt is that one int value is pseudorandomly generated and returned. All 2^32 possible int values are produced with (approximately) equal probability.

public int nextInt(int n) Returns a pseudorandom, uniformly distributed int value between 0 (inclusive) and the specified value (exclusive), drawn from this random number generator's sequence.

===

Java Language Spec regarding the sign of the result of '%'

... It follows from this rule that the result of the remainder operation can be negative only if the dividend is negative, and can be positive only if the dividend is positive. ...

Upvotes: 3

Michael Berry
Michael Berry

Reputation: 72344

Modulo-ing a positive number in Java with a negative one will returning a negative result - which is probably where you're getting behaviour you don't expect.

Perhaps you want something like:

System.out.print(Math.abs(x % 2) + 1);

This isn't precisely defined as far as mathematics go, and thus different languages will implement this in different ways - so it's something to watch out for generally. In Pascal for instance, the result will be positive (as you probably expected for this example), and in C89 at least, it's undefined and thus could do either!

Upvotes: 1

duffy356
duffy356

Reputation: 3716

this is because a negative number % 2 = -1 and then +1 results in 0.

;)

Upvotes: 4

Related Questions