int를 임의의 비트로 채우기위한 접근 방식은 제 생각에는 올바른 방법입니다.
// max number of bits
int i = (int)Math.floor(Math.log(max)/Math.log(2)) + 1;
int rnd = 0;
int mask = 1;
while (i-- > 0) {
rnd = rnd << 1 | randBit();
mask <<= 1; // or: mask *= 2
}
double q = (double)rnd/mask; // range is [0, 1)
return (int)((max + 1) * q);
하는의이 살펴 보겠습니다 : 최대 2의 전원이며 루프에서 떨어져 하나 일 때 알고리즘에만 작동하기 때문에, 나는이 수정을 건의 할 것
i
항상 것입니다 max
이 차지하는 비트 수와 같아야합니다. 루프가 끝나면 rnd
에는 0 또는 1로 임의로 채워진 해당 비트 수가 포함되고 mask-1
에는 1로 채워진 해당 비트 수가 포함됩니다. 따라서 rnd
과 mask-1
의 지수가 0과 1 사이에 균등하게 분포되어 있다고 가정하는 것이 안전합니다.이 값을 max
으로 곱하면 부동 소수점/실수 값으로 균등하게 분산 된 0에서 max
사이의 결과가 나타납니다.
이제이 결과는 정수로 매핑되어야하며 물론 균일하게 분포되기를 원할 것입니다. 여기에서 유일한 캐치는 1입니다. rnd
과 mask-1
의 지수가 정확히 1 일 경우 원하는 결과 범위로 스케일링 할 때 문제가되는 가장자리 경우가 있습니다. 균등하게 분포 된 0 .. max-1
값이 있지만 max
이됩니다. 희소 한 예외.
이 조건을 처리하려면 0에서 1까지의 범위를 가지지 만 1 은 인 몫을 만들어야합니다. 이것은 rnd/mask
에 의해 달성됩니다. 이 범위는 max+1
을 곱하고 int로 캐스팅함으로써 균등하게 확산 된 정수 0 .. max
에 쉽게 매핑 될 수 있습니다.
2의 거듭 제곱 (또는 2의 거듭 제곱 수 : '최대'는 포괄적이거나 배타적 인 경우 명확하지 않음)에 대한 접근법은 합리적입니다. 그러나이 수가 2의 거듭 제곱이 아닐 때 예를 들어, 'max'가 6이라고 할 때. – BeeOnRope
max가 2이면 0에서 7 사이의 결과를 얻습니다. – yacc