| ■7096 / ) |
Re[15]: Long型の乱数を生成する自作クラスをつくりたい |
□投稿者/ ぼのぼの (81回)-(2007/08/30(Thu) 11:34:49)
|
■No7076 (れい さん) に返信
>>ul = umin + ul Mod (umax - umin + 1UL)
>
> こうやって余りを計算してしまうと、
> どうしても偏りが出てしまいます。
>
> umin = 0
> umax = ULong.MaxValue*2/3
>
> となるとULong.MaxValue/3を超える数と超えない数の出現確率は
> 倍違うことになります。
えーと、この状況をわかりやすく図示すると。
min max
0|--------+--------|--------|MAX
こういう状態のときは、剰余分は折り返されるイメージだから、
min max
0|--------+--------| MAX
--------|
↑ここが2倍になってしまう
ということですね。
max-minがもうちょっと小さい場合でも
min max
0|---|---|---|---|---|---|--|MAX
端数分を折り返すと
0|---|---|---|---|---|---| MAX
--|
↑ここだけ2倍になる
min max
0|------|------+------+------|MAX
こういう風にぴったり分割される場合はOK。
ということは、乱数が折り返しのときだけ
サイコロを振りなおすようにする、とすると…
'乱数を範囲内に変換
If umin <> UInt64.MinValue OrElse umax <> UInt64.MaxValue Then
Dim divVal As UInt64 = umax - umin + 1UL
While UInt64.MaxValue Mod (divVal) <> (umax - umin) _
AndAlso Convert.ToUInt64(ul / divVal) = Convert.ToUInt64(UInt64.MaxValue / divVal)
_Random.NextBytes(b)
ul = BitConverter.ToUInt64(b, 0)
End While
ul = umin + ul Mod divVal
End If
こうかな。う〜んあってるのかな?
ループが最も多く発生するのはumax-uminがUInt64.MaxValueの半分より
ちょびっとだけ大きい値の場合だけど、
NextBytesの一様性がある程度のものならこの場合でもNextBytesを呼ぶ回数は約2倍。
と期待されるので、そんなに激しい性能劣化は無いと思われまする。
もっといい方法があるのでしょうか…
|
|