我正在使用C语言编写嵌入式代码,并需要使用rand()函数。不幸的是,控制器的库不支持rand()。我需要一个简单的实现,它要快速运行,但更重要的是具有较小的空间开销,能够产生相对高质量的随机数。有人知道应该使用哪个算法或有示例代码吗?
编辑:这是用于图像处理的,因此“相对高质量”的意思是具有不错的周期长度和良好的均匀性。
我正在使用C语言编写嵌入式代码,并需要使用rand()函数。不幸的是,控制器的库不支持rand()。我需要一个简单的实现,它要快速运行,但更重要的是具有较小的空间开销,能够产生相对高质量的随机数。有人知道应该使用哪个算法或有示例代码吗?
编辑:这是用于图像处理的,因此“相对高质量”的意思是具有不错的周期长度和良好的均匀性。
查看George Marsaglia的随机数生成器集合。他是随机数生成的领先专家,因此我很有信心使用他推荐的任何内容。该列表中的生成器非常小,有些只需要几个无符号长整型作为状态。
Marsaglia的生成器在您对长周期和良好均匀分布的标准下确实是“高质量”的。它们通过了严格的统计测试,但不适用于加密。
使用C代码来实现L'écuyer的LFSR113:
unsigned int lfsr113_Bits (void)
{
static unsigned int z1 = 12345, z2 = 12345, z3 = 12345, z4 = 12345;
unsigned int b;
b = ((z1 << 6) ^ z1) >> 13;
z1 = ((z1 & 4294967294U) << 18) ^ b;
b = ((z2 << 2) ^ z2) >> 27;
z2 = ((z2 & 4294967288U) << 2) ^ b;
b = ((z3 << 13) ^ z3) >> 21;
z3 = ((z3 & 4294967280U) << 7) ^ b;
b = ((z4 << 3) ^ z4) >> 12;
z4 = ((z4 & 4294967168U) << 13) ^ b;
return (z1 ^ z2 ^ z3 ^ z4);
}
非常高质量和快速。在任何情况下都不要使用rand()函数,它比无用更糟糕。
我发现了一些关于种子的问题,并尝试制定强大的种子初始化程序,以便它们不会在给出“错误”的种子值时中断。
维基百科上的一些信息:
它通过了许多统计随机性测试,包括Diehard测试。它通过了大多数,但不是全部,更严格的TestU01 Crush随机性测试。
许多语言的源代码可以在链接中找到。
sizeof(unsigned) == 4
:unsigned t1 = 0, t2 = 0;
unsigned random()
{
unsigned b;
b = t1 ^ (t1 >> 2) ^ (t1 >> 6) ^ (t1 >> 7);
t1 = (t1 >> 1) | (~b << 31);
b = (t2 << 1) ^ (t2 << 2) ^ (t1 << 3) ^ (t2 << 4);
t2 = (t2 << 1) | (~b >> 31);
return t1 ^ t2;
}
我会从GNU C库中选一个,源代码可以在线浏览。
http://qa.coreboot.org/docs/libpayload/rand_8c-source.html
但是,如果您对随机数的质量有任何疑虑,您可能应该更仔细地查看编写得更好的数学库。这是一个大课题,标准的rand
实现并不受专家们的高度评价。
这里还有另一种可能性:http://www.boost.org/doc/libs/1_39_0/libs/random/index.html
(如果您发现选项太多,您总可以随机选择一个。)
鉴于它只有几行代码,应该很容易适应C语言。
编辑:你可以澄清一下“相对高质量”的含义吗?你是为核弹发射代码生成加密密钥,还是为打扑克游戏生成随机数?
有一个简单的 RNG 名为 KISS,它是根据三个数字生成随机数的随机数发生器。
/* Implementation of a 32-bit KISS generator which uses no multiply instructions */
static unsigned int x=123456789,y=234567891,z=345678912,w=456789123,c=0;
unsigned int JKISS32() {
int t;
y ^= (y<<5); y ^= (y>>7); y ^= (y<<22);
t = z+w+c; z = w; c = t < 0; w = t&2147483647;
x += 1411392427;
return x + y + w;
}
还有一个网站可以测试随机数生成器http://www.phy.duke.edu/~rgb/General/dieharder.php