我正在尝试编写一些代码来创建一个伪随机整数序列,该序列使用从 0 到 n 的每个数字,然后重复。天真的方法是创建一个包含 n 个整数的数组,然后以某种方式对它们进行加扰,然后循环遍历它们。那是以空间换速度,但如果可能的话,我需要保留空间。
想到这里让我想起了“FizzleFade”,Wolfenstein 3D 使用红色填充屏幕的算法,一次一个像素,而不用两次填充同一个像素。这很简单(这个例子只打印 X 和 Y 坐标):
uint32_t rndval = 1;
uint16_t x, y;
do {
y = rndval & 0x000FF;
x = (rndval & 0x1FF00) >> 8;
unsigned lsb = rndval & 1;
rndval >>= 1;
if (lsb) {
rndval ^= 0x00012000;
}
if (x < 320 && y < 200)
printf("x: %d y: %d\n", x, y);
} while (rndval != 1);
至少,它看起来很简单。这似乎是一个线性反馈移位寄存器。但是,我不知道如何将此代码调整为 n 位。我不知道他们是如何确定 XOR 值的。我首先尝试将上述代码调整为 8 位值,如下所示:
#include <stdio.h>
#include <stdint.h>
int fizzlefade(void) {
uint8_t rndval = 1;
uint16_t values = 0;
do {
unsigned lsb = rndval & 1;
rndval >>= 1;
if (lsb) {
rndval ^= 0x21;
}
printf("%d\n", rndval);
values++;
} while (rndval != 1);
printf("Total number of values: %d\n", values);
return 0;
}
int main(void) {
printf("Fizzlefade demo\n");
fizzlefade();
return 0;
}
但是,无论我将 XOR 值更改为什么,我都只能得到 N 个值,其中 N < n,对于 8 位值,通常小于 100 个值。我如何确定 XOR 抽头?我需要不同的起始值吗?有比使用 LFSR 更快/更小的方法吗?
编辑:我取得了一些进展。我注意到在原始版本中,rndval 是输出值大小的两倍。所以我将我的 rndval 更改为 16 位无符号,然后将 XOR 更改为 0x1200 以模仿原始代码。这给了我 250 个随机值,都是独一无二的——非常接近!仍然不确定该怎么做。