Java 随机给出负数

2022-08-31 20:27:16

我在Javas类上遇到了麻烦,如果我这样做:Random

Random rng = new Random(seed) // seed == 29 in this example

String ss = "";
        for(int i = 0; i < 10; i++)
        {
            int s = rng.nextInt();
            ss += Integer.toString(s);
            ss +="\n";
        }

这就是我得到的:

-1169335537
-2076183625
1478047223
1914482305
722089687
2094672350
-1234724057
-1614953544
-321574001
1000360613

从我所读到的内容来看,这应该只返回正数作为开始吗?

这可能有点牵强,但它与在Windows 7 64位上运行64位机器没有任何关系?

任何帮助都将是真棒需要完成这项工作,以便在今天完成任务!


答案 1

来自 nextInt() 的 Java 文档

所有 232 个可能的整数值都是以(大约)相等的概率生成的。

一种方法是使用以下转换:

s =  rng.nextInt() & Integer.MAX_VALUE; // zero out the sign bit

需要这样的东西(而不是使用绝对值或否定)的原因是绝对值太大而无法转换为正整数。也就是说,由于溢出,和 。上面的转换保留了近似均匀分布的属性:如果您编写了一个生成和测试循环,该循环只是丢弃并返回了其他所有内容的绝对值,则正整数的可能性将是零的两倍。通过映射到零,使零的概率与正整数对齐。Integer.MIN_VALUEMath.abs(Integer.MIN_VALUE) == Integer.MIN_VALUEInteger.MIN_VALUE == -Integer.MIN_VALUEInteger.MIN_VALUEInteger.MIN_VALUE

这是另一种方法,实际上可能更快一点(尽管我还没有对其进行基准测试):

int s = rng.next(Integer.SIZE - 1); // Integer.SIZE == 32

这将生成一个具有31个随机低阶位的整数(0作为第32位,保证非负值)。但是(正如 jjb 在注释中指出的那样),由于 是 的方法,因此您必须子类来公开该方法(或为该方法提供合适的代理):next(int)protectedRandomRandom

public class MyRandom extends Random {
    public MyRandom() {}
    public MyRandom(int seed) { super(seed); }

    public int nextNonNegative() {
        return next(Integer.SIZE - 1);
    }
}

另一种方法是使用 包装 4 字节数组的 。然后,您可以生成一个随机的四个字节(通过调用),将符号位清零,然后将该值读取为 .我不相信这比上述有任何优势,但我想我会把它扔在那里。它基本上与我的第一个解决方案相同(用 屏蔽)。ByteBuffernextBytes(byte[])intInteger.MAX_VALUE

在这个答案的早期版本中,我建议使用:

int s = rng.nextInt(Integer.MAX_VALUE);

但是,根据文档,这将生成范围为 0(含)到(不含)的整数。换句话说,它不会产生价值 。此外,事实证明,这总是比 .Integer.MAX_VALUEInteger.MAX_VALUEnext(int)nextInt(int)


答案 2

既然正数或负数的几率相等,为什么不直接:

Math.abs(rand.nextInt())

很好,很容易!


推荐