我需要一个计算unsigned val
和signed dX
之和的函数,并将结果包装在范围lower
和upper
例如:
值5
,-6
的更改以及0
和10
的范围将返回10
。
< 1 2 3 4 5 6 7 8 9 10 >
值2
,3
的更改以及1
和3
的范围将返回2
/*
* Given a value and a change in that value (dX), find the sum and wrap it between lower and upper.
*/
unsigned int wrap(unsigned int val, const int dX, const unsigned int lower, unsigned int upper)
{
}
我真的不知道如何处理无符号和带符号的加法/减法以避免下溢。我也不确定如何包装下限。
答案 0 :(得分:2)
首先,计算上限 - 下限以用作模数值并转换为int(根据您的注释,上限 - 下限大于最大有符号整数值的情况不需要处理) :
int modulus = (int)(upper - lower) + 1;
然后你可以用模数模数dX,考虑到包裹:
dX %= modulus;
dX现在的值介于 - (模数-1)和模数-1之间。如果它是负的,只需加上模数:
if(dX < 0)
dX += modulus;
dX
现在保证是积极的,你只需处理溢出。您可以添加val和lower之间的差异,然后再次检查模数。这避免了必须处理无符号溢出。
dX += (val - lower);
if(dX >= modulus)
dX -= modulus;
这为您提供了一个相对于下限的值,您可以使用它来计算新的val:
val = lower + (unsigned int)dX;
答案 1 :(得分:2)
如果您愿意将dx
从const int
更改为int
,则可以循环执行算术。这可以避免upper - lower
超过INT_MAX
时可能出现的问题。
#include <stdio.h>
unsigned int wrap_add(unsigned int val,
int dx,
const unsigned int lower,
const unsigned int upper);
int main(void)
{
printf("Range [0, 10]: 5 + (-6) = %u\n", wrap_add(5, -6, 0, 10));
printf("Range [1, 3]: 2 + 3 = %u\n", wrap_add(2, 3, 1, 3));
printf("Range [2, 5]: 2 + (-9) = %u\n", wrap_add(2, -9, 2, 5));
return 0;
}
unsigned int wrap_add(unsigned int val,
int dx,
const unsigned int lower,
const unsigned int upper)
{
while (dx < 0) {
if (val == lower) {
val = upper;
} else {
--val;
}
++dx;
}
while (dx > 0) {
if (val == upper) {
val = lower;
} else {
++val;
}
--dx;
}
return val;
}
节目输出:
Range [0, 10]: 5 + (-6) = 10
Range [1, 3]: 2 + 3 = 2
Range [2, 5]: 2 + (-9) = 5