介绍
今天在看 karpathy 大神的llama2.c 的代码,里面使用了xorshift 随机数生成器,自己用C#实现了一次,记录下自己的理解。
xorshift 随机数生成器是一种基于位操作的伪随机数生成算法,由 George Marsaglia 在 2003 年提出。它通过异或操作与移位操作混合来生成随机数,并且相较于传统的线性同余生成器来说具有较好的随机性和性能。虽然 xorshift 通常用于需要生成快速伪随机数的场景。
优点
- 性能:由于它的操作主要是简单的移位和异或,所以 xorshift 通常比其他复杂的生成器(如 Mersenne Twister)更快。
- 可预测性:通过种子可以再现随机数序列,这在测试和调试中非常有用。
缺点
- 随机性问题:与更复杂的生成器相比,xorshift 可能在高维空间或长序列下表现出一定的模式,使它不适用于某些高随机性要求的应用,例如加密。
- 周期性问题:xorshift 的周期性依赖于其内部状态的长度。在某些配置下,周期可能较短。
适用场景
- 适合:对于图形学、模拟、非加密性应用程序,xorshift 是一种良好的选择,尤其当需要快速产生大量随机数时。
- 不适合:对于密码学、安全性要求较高的场景或某些科学模拟,建议选择更高随机性的生成器(如 RandomNumberGenerator 或 Mersenne Twister)。
综上所述,xorshift 是一种可靠的生成器,在适当的应用场景中可以胜任。但是,如果应用对随机性和安全性要求较高,应当使用加密安全的随机数生成器。
C#实现
下面我买实现了一个xorshift 随机数生成器的C#版本
using System;
class RandomNumberGenerator
{
// 内部保存状态变量
private ulong state;
// 构造函数,接受初始状态
public RandomNumberGenerator(ulong initialState)
{
state = initialState;
}
// 生成一个32位的无符号整数
private uint RandomU32()
{
state ^= state >> 12;
state ^= state << 25;
state ^= state >> 27;
return (uint)((state * 0x2545F4914F6CDD1DUL) >> 32);
}
// 生成一个在[0, 1)区间的float32随机数
public float RandomF32()
{
return (RandomU32() >> 8) / 16777216.0f;
}
}
ulong initialState 是生成随机数的初始种子值,用于设定伪随机数生成器的初始状态。每次生成器被实例化时,它的内部状态将从这个初始种子值开始。随机数生成器依赖于内部状态的变化产生随机数,如果您为 initialState 设置一个固定值,那么生成的随机数序列也将是确定的(即伪随机)。
- 如果您希望生成相同的随机数序列(例如测试或调试目的),您可以设置一个固定的 initialState 值。这样,每次生成器都会产生相同的随机数序列。
- 如果您希望确保生成的随机数序列尽可能不可预测,您可以使用系统时间、硬件熵源、或者其他随机事件来初始化 initialState。
使用例子
class Program
{
static void Main()
{
// 使用当前系统时间的刻度数作为种子
ulong seed = (ulong)DateTime.Now.Ticks;
// 实例化随机数生成器
RandomNumberGenerator rng = new RandomNumberGenerator(seed);
// 生成随机数
float randomValue = rng.RandomF32();
Console.WriteLine($"Generated Random Float: {randomValue}");
}
}