我正在开发一个受到严格监管审查的游戏平台。我之所以选择Math.NET,是因为它看起来很合适。不过,我刚从审计员那里收到了这条评论。
请注意这是否准确以及如何解决?
在RandomSource()中,Next(int,int)定义如下:
public override sealed int Next(int minValue, int maxValue)
{
if (minValue > maxValue)
{
throw new ArgumentException(Resources.ArgumentMinValueGreaterThanMaxValue);
}
if (_threadSafe)
{
lock (_lock)
{
return (int)(DoSample()*(maxValue - minValue)) + minValue;
}
}
return (int)(DoSample()*(maxValue - minValue)) + minValue;
}
这会以与以前相同的方式产生偏差。使用来自RNG的未缩放值并将其乘以该范围而不预先消除偏差(除非范围是2的幂,否则将存在偏差)。
答案 0 :(得分:2)
更新 :在此讨论之后,Math.NET Numerics v3.13中的Next(minInclusive, maxExclusive)
实现已更改。从v3.13开始,它不再涉及浮点数,而是采用具有所需位数的整数来支持所请求的范围(2的幂)并拒绝实际范围之外的那些。这样就避免了在字节采样本身之上添加任何偏差(例如由加密RNG提供)
假设:DoSample()
返回[0,1)
范围内的均匀分布样本(双精度浮点数)。
将其乘以范围R = max-min将导致[0,R)
范围内的均匀分布样本。将其转换为整数(基本上是一个平面)将导致0,1,2,...,R-1
之一的均匀分布的离散样本。在这一步中,我没有看到R是偶数,奇数或2的幂可能影响偏差的事实。
计算100'000'000样本的几次运行也没有表明明显的偏差,但当然这不是证明:
var r = new CryptoRandomSource();
long[] h = new long[8];
for (int i = 0; i < 100000000; i++)
{
h[r.Next(2,7)]++;
}
0
0
19996313
20001286
19998092
19998328
20005981
0
0
0
20000288
20002035
20006269
19994927
19996481
0
0
0
19998296
19997777
20001463
20002759
19999705
0
答案 1 :(得分:0)
我已经为这个解决方案提供了0到最大值之间的值。我不是数学专家所以欢迎评论。
它似乎符合我所说的监管规范
2b)如果选择的特定随机数超出了重新缩放值的相等分布范围,则允许丢弃该随机数并按顺序选择下一个以进行重新缩放。“
private readonly CryptoRandomSource _random = new CryptoRandomSource();
private int GetRandomNumber(int max)
{
int number;
var nextPowerOfTwo = (int)Math.Pow(2, Math.Ceiling(Math.Log(max) / Math.Log(2)));
do
{
// Note: 2nd param of Next is an *exclusive* value. Add 1 to satisfy this
number = _random.Next(0, nextPowerOfTwo + 1);
} while (number > max);
return number;
}