Linear congruential generator是一个很好的算法。但是有更快的算法吗?
答案 0 :(得分:4)
由于8位CPU通常不能进行快速除法甚至乘法,因此使用线性同余生成器通常不是一个好主意。
Linear feedback shift register (LFSR)仅使用移位和逻辑运算。
如果使用数组,它将成为广义线性反馈移位寄存器(GLFSR),这是Mersenne Twister使用的一般方法。它循环遍历数组,而不是在每一步移动所有位,这样你就可以拥有一个很大的状态空间(数百到数千位)而且计算量很小。
请注意,由于它是线性方法,因此不适用于加密。
答案 1 :(得分:2)
我记得8051有一个8x8 = 16位乘法器,因此实现lag-n multiply-with-carry生成器可能是可行的。这种技术的优点是,如果你能找到一个合适的安全素数,你可以用很少的算术得到很长一段时间。
不幸的是,似乎没有太多的安全素数选项,乘法器只有8位,我担心短的乘数可能会导致一些通常不会出现在MWC中的弱点。
我只是将它们组合在一起,虽然我不是100%肯定它正确地实现了MWC,但它实际上通过了大量的dieharder测试:
#define STATE_BYTES 7
#define MULT 0x13B /* for STATE_BYTES==6 only */
#define MULT_LO (MULT & 255)
#define MULT_HI (MULT & 256)
uint8_t rand8(void)
{
static uint8_t state[STATE_BYTES] =
{ 0x87, 0xdd, 0xdc, 0x10, 0x35, 0xbc, 0x5c };
static uint16_t c = 0x42;
static int i = 0;
uint16_t t;
uint8_t x;
x = state[i];
t = (uint16_t)x * MULT_LO + c;
c = t >> 8;
#if MULT_HI
c += x;
#endif
x = t & 255;
state[i] = x;
if (++i >= sizeof(state))
i = 0;
return x;
}
如您所见,乘数实际上是9位,但我们使用shift-and-add来实现硬件乘法器无法管理的最后一位。
在进一步测试中,我发现了一个合适的89位安全素数,几乎可以通过所有的顽固分子。改变这些行:
#define STATE_BYTES 10
#define MULT 0x153 /* for STATE_BYTES==10 only */
我用这个种子进行测试:
static uint8_t state[STATE_BYTES] =
{ 0x87, 0xdd, 0xdc, 0x10, 0x35, 0xbc, 0x5c, 0xb6, 0xca, 0x0a, };
static uint16_t c = 0x42;
种子只是来自/ dev / random的一些内容,您可以自由选择。然而,增加州的规模基本上是作弊,因为它允许种子的质量在随机性测试的成功或失败中发挥更大的作用。可能是糟糕的种子可能导致非常随机的结果。
答案 2 :(得分:0)
不,通过通用CPU没有明显更快的算法。正如@Joachim Isaksson和@Michael Burr所提到的,如果不降低质量或做一些奇怪的事情,就没有什么可以做的。 g:在编译时计算一大堆随机数,然后运行时生成很快。
任何真正的快速随机数发生器都使用专用硬件。由于您已标记[微控制器],请查看您正在使用的处理器,以查看它可能提供的专用功能。
此外:为您的PRN需求提供更多信息可能有助于引出一些新颖的想法(数字长度,速度:O(n)或时间,随机程度等),例如使用微控制器基于时间的计数器修改一个伟大的素数。