来自Fastest way to generate a random boolean,在评论中,CodesInChaos说:
MS搞砸了
NextBytes
的实施,所以它的速度非常慢。[...]性能与为每个字节调用
Next
一样糟糕,而不是利用所有31位。但是由于System.Random
在几乎每个级别都有糟糕的设计和实现,这是我较小的抱怨之一。
为什么他说MS在几乎每个级别都进行了设计和实现?
如何错误地实施Random
类?
答案 0 :(得分:2)
当然,由于他的原因,我无法理解他的内心,但System.Random
非常奇怪。
InternalSample()
会返回不能为int
的非负int.MaxValue
。这在一开始听起来并不那么糟糕,但这意味着它几乎(但不完全)是31个可用的随机位。这使得有效实施NextBytes(byte[] buffer)
之类的事情变得复杂,它甚至没有尝试过!它这样做:
for (int index = 0; index < buffer.Length; ++index)
buffer[index] = (byte) (this.InternalSample() % 256);
对InternalSample
的调用次数大约是必要的4倍。此外% 256
无用,无论如何都会转换为字节截断。它也有偏见,因为内部样本不能是int.MaxValue
,所以255 比其他任何结果都 。
但它变得更糟。例如,NextDouble
使用this.InternalSample() * 4.6566128752458E-10
。这可能不是很明显,但4.6566128752458E-10
是1.0 / int.MaxValue
。令人烦恼的是,它不是两个人的力量,所以它是一个混乱的&#34;导致相邻可能结果之间的间隙不均匀的数字。
更糟糕的是,Next(int)
和Next(int, int)
的算法本质上是有偏见的,因为它们只是缩放随机双精度而拒绝任何东西。它也不是特别快,这通常是避免拒绝抽样的原因。
总的来说它也相当慢。它是一个减法生成器,一个相对未知的PRNG,显然不是太糟糕,但它有一个很大的状态(播种速度慢,并且有一个恼人的缓存占用空间)和一些烦人的操作采样算法。当然它比基本的LCG具有更好的质量,但它被偏差的缩放方法和糟糕的性能严重损害。
界面设计也很烦人。由于上限到处都是独占的,因此没有简单的方法可以在[0 .. int.MaxValue]或[int.MinValue .. int.MaxValue]中生成样本,这两种方法都非常常用。独特的上限往往很好,以避免奇怪的-1,没有办法得到全范围的样本只是烦人。当然可以通过NextDouble
来完成,但由于NextDouble
的输入已经不是全范围样本,因此结果必然存在偏差。
我可能错过了一些不足之处。