|
func Roll(src *rand.PCGSource, dicePoints IntType, mod int) IntType { |
|
if dicePoints == 0 { |
|
return 0 |
|
} |
|
if mod == -1 { |
|
return 1 |
|
} |
|
if mod == 1 { |
|
return dicePoints |
|
} |
|
if src == nil { |
|
src = randSource |
|
} |
|
// js端有bug,如果当前IntType为32位,Int63会得到负数 |
|
// val := IntType(rand.Int31())%dicePoints + 1 |
|
// 同样问题也存在于这里,所以需要 &math.MaxInt32 |
|
val := IntType(src.Uint64()&math.MaxInt32)%dicePoints + 1 |
|
return val |
|
} |
在 39 行对生成的随机数直接使用了取模运算. 由于生成的随机数是在非负 int32 上均匀的, 当 dicePoints 不是 2 的幂时, 导致较小余数出现的概率将比较大余数大.
如何验证问题存在: 统计 d1431000000 的分布. 由于这个数足够大, 可以使小出目的概率达到大出目的 2 倍.
dicescript/roll_func.go
Lines 23 to 41 in 28fab8c
在 39 行对生成的随机数直接使用了取模运算. 由于生成的随机数是在非负 int32 上均匀的, 当
dicePoints不是 2 的幂时, 导致较小余数出现的概率将比较大余数大.如何验证问题存在: 统计 d1431000000 的分布. 由于这个数足够大, 可以使小出目的概率达到大出目的 2 倍.