我需要在 C 中生成一些随机数来测试和调试系统。该系统是一个自定义硬件 (SoC),具有一组有限的功能,因此我只能使用基本的数学运算。
不,我不能在 stdlib 或 math.h 中使用随机数生成器。我需要自己写。那么是否有某种算法可以生成随机数?
我知道一个简单的解决方案是在我的工作站上生成数字并将它们嵌入到模块中,但我不想这样做。
我需要在 C 中生成一些随机数来测试和调试系统。该系统是一个自定义硬件 (SoC),具有一组有限的功能,因此我只能使用基本的数学运算。
不,我不能在 stdlib 或 math.h 中使用随机数生成器。我需要自己写。那么是否有某种算法可以生成随机数?
我知道一个简单的解决方案是在我的工作站上生成数字并将它们嵌入到模块中,但我不想这样做。
只需挖掘 Park 和 Miller 在 CACM 10 月 88 日发行的文章即可。
他们提出的一般算法是:
a = 16807;
m = 2147483647;
seed = (a * seed) mod m;
random = seed / m;
虽然这篇文章包括一些改进。
随机数生成器基本上是一个特殊的*散列函数,它从起始种子递归运行。
我在我的 C# 代码中使用了MurmurHash2 算法,效果很好。它非常快速且易于实现,并且已经过测试,它的分布非常好,碰撞率低。该项目有几个用 C++ 编写的不同的开源散列函数,应该可以很容易地转换为 C。
* 特殊我的意思是对一个值运行哈希函数应该返回另一个看似随机(但确定)的值,这样输出就不会形成模式。此外,返回值的分布应该是均匀分布的。
您可能想寻找梅森捻线机。有很多更高质量的算法。一篇很好的文章,您可以在这里找到概述:
检查gsl 库的源代码,其中实现了几个经过良好测试的算法。
你可以试试George Marsaglia的 Multiply-with-carry。
来自维基百科的代码:
#include <stdint.h>
#define PHI 0x9e3779b9
static uint32_t Q[4096], c = 362436;
void init_rand(uint32_t x)
{
int i;
Q[0] = x;
Q[1] = x + PHI;
Q[2] = x + PHI + PHI;
for (i = 3; i < 4096; i++)
Q[i] = Q[i - 3] ^ Q[i - 2] ^ PHI ^ i;
}
uint32_t rand_cmwc(void)
{
uint64_t t, a = 18782LL;
static uint32_t i = 4095;
uint32_t x, r = 0xfffffffe;
i = (i + 1) & 4095;
t = a * Q[i] + c;
c = (t >> 32);
x = t + c;
if (x < c) {
x++;
c++;
}
return (Q[i] = r - x);
}