1

我需要一些帮助来调试以下 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 教程说不。还是我还缺少其他东西?

4

4 回答 4

4

这是因为负数 % 2 = -1 然后 +1 结果为 0。

;)

于 2013-05-03T16:05:34.527 回答
3

注意

Random.nextInt()

可能会产生负整数,并且在 Java 中,余数运算符 ('%') 的结果采用左侧操作数的符号。这在编程语言之间有所不同 - 请参阅Wikipedia 条目中的此表以获取 Modulo 示例

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

Random.nextInt(Integer.MAX_VALUE)

产生 0(含)和 2^31-1(不含)之间的整数。否则,如果您想处理模数可能的负结果并且仍然只返回 1 或 2,请使用:

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

===

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

public int nextInt()从该随机数生成器的序列中返回下一个伪随机、均匀分布的 int 值。nextInt 的一般约定是伪随机生成并返回一个 int 值。所有 2^32 个可能的 int 值都是以(大约)相等的概率产生的。

public int nextInt(int n)返回一个伪随机、均匀分布的int 值,介于 0(包括)和指定值(不包括)之间,取自此随机数生成器的序列。

===

Java 语言规范关于“%”结果的符号

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

于 2013-05-03T16:46:15.853 回答
1

将 Java 中的正数与负数取模将返回负数结果——这可能是你得到意想不到的行为的地方。

也许你想要类似的东西:

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

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

于 2013-05-03T16:06:54.747 回答
1

Guava 的 IntMath类提供了一个始终为正的模运算:

System.out.println(IntMath.mod(x, 2) +1); 
于 2013-05-12T13:17:00.543 回答