Reputation: 16640
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
Reputation: 2962
Guava's IntMath
class offers an always positive modulo operation:
System.out.println(IntMath.mod(x, 2) +1);
Upvotes: 1
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
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
Reputation: 3716
this is because a negative number % 2 = -1 and then +1 results in 0.
;)
Upvotes: 4