这必须是非常简单的数学,但我不知道如何解决它。
我需要编写一个函数,以1到3的比例返回一个数字,如下所示:
input: -5 output: 1
input: -4 output: 2
input: -3 output: 3
input: -2 output: 1
input: -1 output: 2
input: 0 output: 3
input: 1 output: 1
input: 2 output: 2
input: 3 output: 3
input: 4 output: 1
input: 5 output: 2
input: 6 output: 3
input: 7 output: 1
以下功能适用于正数
static const int getOnScaleOneToThree(int input)
{
int x = ceil(input / 3);
return abs((input - (x * 3)));
}
但它反过来(当然)负面输入如下:
input: -6 output: 3
input: -5 output: 2
input: -4 output: 1
input: -3 output: 3
input: -2 output: 2
input: -1 output: 1
input: 0 output: 3
input: 1 output: 1
input: 2 output: 2
input: 3 output: 3
有什么想法吗? 谢谢!
答案 0 :(得分:2)
这应该有效,并且避免使用负数的模运算的依赖于实现的结果。
if(input >= 0)
{
return (1 + ((input + 2) % 3));
}
else
{
return (3 - ((-input) % 3));
}
此外,这是一个更通用(和详细)的解决方案:
static const int getOnScale(int input, int minVal, int maxVal, int zeroVal)
{
if(input == 0)
{
//Might as well return this right away.
return zeroVal;
}
else
{
if(maxVal >= minVal)
{
int divisor = maxVal - minVal + 1;
if(input > 0)
{
int dividend = input + zeroVal - minVal;
return (minVal + (dividend % divisor));
}
else
{
int dividend = maxVal - zeroVal - input;
return (maxVal - (dividend % divisor));
}
}
else
{
//Reverse scale
int divisor = minVal - zeroVal + 1;
if(input > 0)
{
int dividend = minVal - zeroVal + input;
return (minVal - (dividend % divisor));
}
else
{
int dividend = -input + zeroVal - maxVal;
return (maxVal + (dividend % divisor));
}
}
}
}
在这个问题的情况下,这个函数将被称为:
getOnScale(input, 1, 3, 3);
答案 1 :(得分:1)
您可以使用LUT(查找表)。这是一些伪代码:
int output[] = { 3, 2, 1, 3, 2, 1, 3, 1, 2, 3 };
assert(input >= -6 && input <= 3);
int index = input+6;
int value = output[index];
LUT超快,易于维护,非常适合在运行时难以计算的奇怪映射。
当输入范围很大时,它们会产生挑战 - 内存需求显然可以达到平流层。有解决方案,例如:
答案 2 :(得分:1)
尝试:
int out( int in )
{
return ( in >= 0 ) ? ( ( in + 2 ) % 3 ) + 1 : 3 - ( -1 * in % 3 ); }
}
当被除数低于零并且除数为正时,实现定义的行为的好处。
答案 3 :(得分:1)
static const int getOnScaleOneToThree(int input)
{
return (int)((unsigned int)(input + 0x80000000)%3 + 1);
}
如果int
为32位,则此方法有效。
答案 4 :(得分:1)
好吧,我一直在考虑这个问题,但基于此:
https://meta.stackexchange.com/q/213976/171816
我只想将此作为额外答案发布,并参考其他问题的答案。
另一个答案比我的第一个答案更优雅:https://stackoverflow.com/a/1082938/982107
将模数函数写为
static int mod(int x, int m)
{
int r = x%m;
return r<0 ? r+m : r;
}
即使x为负数,您也会得到正确的答案。
这将允许您编写如下函数:
static int getOnScaleOneToThree(int input)
{
return (mod((input + 2), 3) + 1);
}
这里再次提供了一般解决方案,这次将代码量保持在最低限度:
static int getOnScale(int input, int minVal, int maxVal, int zeroVal)
{
int dividend = input;
if(minVal > maxVal)
{
//Alter values for reverse scale
std::swap(minVal, maxVal);
dividend *= -1;
}
dividend += (zeroVal - minVal);
int divisor = maxVal - minVal + 1;
return (mod(dividend , divisor) + minVal);
}
答案 5 :(得分:0)
重要的是不要纠结于过早的优化,所以以下可能就足够了。
long get_remainder(long n) {
long * remainders = new[(unsigned int)0xffffffff];
long remainder = 1;
for ( long i = LONG_MIN; i < LONG_MAX; ++i ) {
remainders[i + -LONG_MIN] = remainder++;
if ( remainder > 3 )
remainder = 1;
}
int rtn = remainders[n + -LONG_MIN];
delete[] remainders;
return rtn;
}
像这样使用:
for ( int i = -10; i < 10; ++i )
{
int remainder = get_remainder(i);
}