0

我想要一个从 0 到 3 的随机数,并尝试了下面的代码来看看它是如何工作的。

int[] count = new int[4];

    for (int i = 0; i < 1000; i++) {
        int t = (int)(Math.round((Math.random() *3)));

        count[t] +=1;

    }


    for (int i = 0; i < count.length; i++) {
        System.out.println(count[i]);

    }

现在奇怪的是,0 和 3 命中大约是 1 和 2 命中的一半,这怎么可能?

4

4 回答 4

6

查看四舍五入到每个整数的间隔:

|----+----|----+----|----+----|
0         1         2         3

<...>
Rounds to 0
     <........>
     Rounds to 1
               <........>
               Rounds to 2
                         <....>
                         Rounds to 3

您可以看到,舍入到 0 和 3 的范围是其他范围的一半,因此如果您选择统一,则命中它们的频率是一半。

于 2013-03-10T04:42:59.423 回答
2

http://docs.oracle.com/javase/6/docs/api/java/lang/Math.html#round(double)

返回最接近参数的 long。通过加 1/2、取结果的下限并将结果转换为 long 类型,将结果四舍五入为整数。

您正在创建大小不等的存储桶:

0 - 0.4999... => 0 (.5)

0.5 - 1.499... => 1 (1)

1.5 - 2.499... => 2 (1)

2.5 - 2.99999... => 3 (.5)

要修复,请使用:

Random.nextInt(4);

呃......错字,谢谢@TedHopp - 我的意思是:

Random r = new Random();
...
r.nextInt(4);

或者做

(int) (Math.random() * 4);s

这会做你所期望的。

于 2013-03-10T04:45:18.633 回答
1

发生这种情况是因为您正在四舍五入。0 只能在小于 0.5 时四舍五入。但是,如果它在 0.5 和 1.5 之间,则可以选择 1。因此,给它两倍的发生机会。同样的事情发生在 2 上,介于 1.5 和 2.5 之间。而 3 只是从 2.5 到 3。

于 2013-03-10T04:42:18.857 回答
1
class Math {
    ...
    public static long round(double a) {
       return (long)floor(a + 0.5d);
    }
    ...
}

击中1和2的概率更大

int t = (int)(Math.ceil((Math.random() * 4))) - 1;

使用 ceil 而不是 round 可以提供更好的分布:

250
239
242
269
于 2013-03-10T06:30:49.107 回答