假设有一个包含 8 个元素的数组:
buff[8] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17}
我们想要实现数组的模索引
预期结果:
buff[3]=0x13
增益[-22] = 0x12
buff[47]=0x17
buff[-16] = 0x10
这里,模索引是指根据数组的大小重新设置数组索引,遵循从0开始的标准索引。
在 GCC 编译器中,对于给定的示例,Modulo-8 的集合是 [-7 到 7],示例:
1 % 8 = 1; 16 % 8 = 0; 23 % 8 = 7; -8 % 8 = 0;
-1 % 8 = -1; -16 % 8 = 0; -23 % 8 = -7; 8 % 8 = 0;
这里股息是指数,除数 8 是 buffer_len = 8
根据数字的符号,我们得到相应的模数,而余数 0 在正整数和负整数中都是重叠的。
[-7 to 0] for negative numbers and [0 to 7] for positive numbers.
但是我们的范围应该是[0到7]。从数学上来说,我们想要映射负索引,使得索引 -1 与索引 7 相同; -2 与索引 6 相同,依此类推。
为了接近解决方案,我们有一个执行模数运算的起点,它为我们提供了上述范围从 [-7 到 7] 范围内的有符号值。
index % buffer_len ---------------------> (1)
第二步是将负数映射到对应的正数上(给出相同余数的全等数 -1&7、-2&6,...)
为此,我们可以简单地将缓冲区大小添加到集合 [-7 到 7] 的各个元素中。 将 buffer_len 添加到 eq. (1)
buffer_len + ( index % buffer_len ) ---------------------> (2)
这样做我们只是简单地绘制地图
-7 -> -7+8 = 1; -6 -> -6+8 = 2 ... and -1 -> -1+8 = 7, and 0 -> 0+8 = 8,
但这也调整了我们的正数,
1 -> 1+8 = 9; 2 -> 2+8 = 10 ... and 7 -> 7+8 = 15
我们得到一组范围从[1到15]的索引 根据模数的定义,如果它们给出相同的余数,则它们是全等的。因此,取该集合的模 8 将为我们提供最终的索引集,即 [0 到 7]。
对式(2)取模8(modulus-buffer_len)
( buffer_len + ( index % buffer_len ) ) % buffer_len
在这里我们得出结论,为任意大小的数组设置模索引。
最终解决方案:
#define RELATIVE_INDEX(buffer_len, index) ((buffer_len + (( index ) % buffer_len)) % buffer_len)