Java模运算符优先级

时间:2013-05-03 16:00:31

标签: java random modulo

我需要一些帮助来调试以下java程序。

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("");
    }
}

将输出(例如):

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

我认为输出应该只包含一个和两个!如果我们考虑x % (2+1)解释,那么输出是正确的。模数运算符真的比加法弱吗? Java tutorial说不。或者还有其他我想念的东西?

4 个答案:

答案 0 :(得分:4)

这是因为负数%2 = -1然后+1会产生0。

答案 1 :(得分:3)

请注意

Random.nextInt()

可能产生负的整数,并且在Java中,余数运算符('%')的结果需要the sign of the left-hand operand。这在编程语言中有所不同 - 请参阅this table in the Wikipedia entry for Modulo for a sampling

如果您只想要非负的整数,请使用:

Random.nextInt(Integer.MAX_VALUE)

生成0(含)和2 ^ 31-1(不包括)之间的整数。否则,如果你想处理模数的可能负面结果并仍然只返回1或2,那么使用:

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

===

Random.nextInt的JavaDoc(重点是我的):

  

public int nextInt()统一返回下一个伪随机数   从该随机数生成器的序列中分配int值。   nextInt的一般契约是一个int值   伪随机生成并返回。 所有2 ^ 32个可能的int值   以(近似)相等的概率产生。

     

public int nextInt(int n)统一返回伪随机数   分布在<0>(包括)和指定值之间的 int值   (独家) ,从这个随机数生成器的序列中抽取。

===

关于the sign of the result of '%'

的Java语言规范
  

......根据这个规则,只有当被除数为负时,余数运算的结果才可以是负数,只有当被除数为正时才能为正数。 ...

答案 2 :(得分:1)

使用负数模拟Java中的正数将返回否定结果 - 这可能是您获得不期望的行为的地方。

也许你想要这样的东西:

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

就数学而言,这并没有精确定义,因此不同的语言将以不同的方式实现这一点 - 因此需要注意一般情况。例如,在Pascal中,结果将是正数(正如您可能对此示例所预期的那样),至少在C89中,它是未定义的,因此可以执行任何操作!

答案 3 :(得分:1)

Guava's IntMath类提供了一个始终正模的操作:

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