C++ 无符号模环绕数组
我正在尝试实现一个最大整数的伪随机数生成器。它维护一个值数组C++ 无符号模环绕数组,c++,c,arrays,random,circular-buffer,C++,C,Arrays,Random,Circular Buffer,我正在尝试实现一个最大整数的伪随机数生成器。它维护一个值数组 int values[SIZE] = { /* 55 seed values */ }; 并使用以下函数返回下一个值 unsigned lagfib() { static unsigned idx = 0; int r = values[idx]; /* The following does not work: */ values[idx] = (values[(idx-24) % SIZE] +
int values[SIZE] = { /* 55 seed values */ };
并使用以下函数返回下一个值
unsigned lagfib()
{
static unsigned idx = 0;
int r = values[idx];
/* The following does not work: */
values[idx] = (values[(idx-24) % SIZE] + values[(idx-55) % SIZE])
% MAX_VALUE;
idx = (idx+1) % SIZE;
return r;
}
实际上,值
应该是一个总是满的简单环形缓冲区。减法和模运算应该将索引环绕到数组的末尾SIZE
应始终至少为55,但我想将其四舍五入到64以加快模运算速度
但很明显,我的模计算错了,我不知道如何修正它们。将索引类型更改为int
并不能改善情况
(PS:是的,代码> static < /COD>数据是坏的样式,但我希望这对于C和C++程序员都是可读的,因为它属于两种语言)。< /P> < P>如果例如代码> IDX 小于24,你将被打包到代码的编号范围的另一端。55不是除数,例如2^32,因此这不会给出正确的结果
我可以看到两种选择:- 维护三个独立的
变量,分别偏移24和55idx
- 执行例如
(idx-24+尺寸)%SIZE
idx = ((SIZE-1) == idx) ? 0 : (idx+1);
这可能比计算模要快得多。您正在使用负索引访问值。例如:
-24 % 55 == -24
因此,需要一些逻辑来结束数组。C/C++不会为您这样做。让我们采用
idx=0
和SIZE=64
(idx-24)%SIZE
将是一个非常大的值(4294967272
对于32位int),因为idx
是无符号的,这使得它成为无效索引
要获得圆形效果,应在取模数之前添加尺寸:
(idx-24+SIZE)%SIZE
将是(0-24+64)%64
,其计算结果为40
+1并被接受,但我假设模64被编译为位掩码运算。我真的应该刷新我的模算术。@larsmans:哦,那么你的代码中确实有SIZE==64
,您是否考虑到种子值需要“反向”排列?返回到SIZE=55
,并注意到idx+55-SIZE
现在是idx
,因此我只需要两个索引。谢谢!为什么是<代码>静态< /代码>数据坏样式(在C中,或者仅仅是C++)?它也是坏的样式,因为它导致不可重入代码。@ EndoList:因为它使代码不线程安全。@拉斯曼:为什么那么糟糕?或者更确切地说,什么时候是糟糕的?如果语言结构总是不好的话,它就不会存在,是吗?@endolith:我倾向于以线程安全的方式编写代码,除非我在做这样的实验。是的,static
有一个用途,就是这样,但只有这是一个一次性的程序。