我需要一些帮助来调试以下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说不。或者还有其他我想念的东西?
答案 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);