Java:生成具有对数分布的随机数

bgu*_*uiz 3 java random math logarithm distribution

我试图生成一个具有对数分布的随机数.

其中n = 1出现一半的时间,n = 2出现四分之一的时间,n = 3出现八分之一的时间,等等.

    int maxN = 5;
    int t = 1 << (maxN); // 2^maxN
    int n = maxN -
            ((int) (Math.log((Math.random() * t))
            / Math.log(2))); // maxN - log2(1..maxN)
    System.out.println("n=" + n);
Run Code Online (Sandbox Code Playgroud)

大多数时候,我得到了我需要的结果,但是每隔一段时间,我得到一个n大于的值maxN.

为什么会这样?我看到它的方式,最大值Math.random()是1.0;
因此最大值(Math.random() * t))t;
因此,log2(t)的最大值是maxN,因为t = 2 ^ maxN;

我的逻辑在哪里偏离轨道?

谢谢

Abh*_*kar 7

数字小于1.0的对数为负数.当生成的随机数小于1.0时,表达式((int) (Math.log(Math.random() * t) / Math.log(2)))为负数,因此maxN - (the negative number)大于maxN.

以下表达式应该给出正确的分布.

n = Math.floor(Math.log((Math.random() * t) + 1)/Math.log(2))
Run Code Online (Sandbox Code Playgroud)

注意:

0.0 <= Math.random() <= 1.0
0.0 <= Math.random() * t <= t
1.0 <= (Math.random() * t) + 1 <= t + 1.0
0.0 <= Math.log((Math.random() * t) + 1) <= Math.log(t + 1.0)
0.0 <= Math.log((Math.random() * t) + 1)/Math.log(2) <= Math.log(t + 1.0)/Math.log(2)

Since t = 2^maxN,
Math.log(t + 1.0)/Math.log(2) is slightly larger than maxN.

So do a Math.floor and you get the correct result:
0.0 <= Math.floor(Math.log((Math.random() * t) + 1)/Math.log(2)) <= maxN
Run Code Online (Sandbox Code Playgroud)