如何简单地循环自定义比例
How to simply loop a custom scale
这一定是一个非常简单的数学,但我不知道如何解决它。
我需要写一个函数,返回一个从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
有什么想法吗?谢谢
这应该有效,并避免了负数模运算的依赖于实现的结果。
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);
您可以使用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速度极快,易于维护,非常适合在运行时难以计算的奇怪映射。
当输入范围很大时,它们构成了一个挑战——内存需求显然可以达到平流层。有一些解决方案,例如:
- 使用线性函数的近似(将输入范围映射到线性函数(
- 多项式逼近
- 测距图
static const int getOnScaleOneToThree(int input)
{
return (int)((unsigned int)(input + 0x80000000)%3 + 1);
}
如果int
是32位,则此操作有效。
尝试:
int out( int in )
{
return ( in >= 0 ) ? ( ( in + 2 ) % 3 ) + 1 : 3 - ( -1 * in % 3 ); }
}
当被除数低于零且除数为正时,实现定义的行为的优点。
好吧,我已经考虑了一段时间,但基于此:
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);
}
重要的是不要卷入过早的优化中,因此以下内容可能就足够了。
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);
}
相关文章:
- 在C++中循环访问自定义结构列表的小问题
- 具有迭代器和自定义步长的循环结束条件
- 循环访问自定义双链表
- C++11:没有复制构造函数的自定义基于范围的循环
- 如何在C++中循环浏览自定义列表
- 基于范围的 for 循环,用于包含C++中的指针的自定义链表,仅返回对象
- 自定义对象构造函数在循环外部循环
- 带有自定义对象的C 范围循环
- glib:在另一个线程上处理自定义 GMainContext* 循环,不引发信号处理程序
- 尝试在自定义 QT 创建器文本编辑器中创建查找和替换循环.我似乎无法设置光标位置
- 从自定义链接列表中打印值时,循环陷入无限时
- 在自定义容器类上反转基于范围的 for 循环
- 如何实现我的自定义范围循环
- C++ while 循环在自定义文件结构中
- 具有自定义步骤的循环的C 范围
- Qt-如何在不使用插槽的情况下检测自定义事件循环中的关闭窗口
- 对话框消息是否发送到自定义消息循环
- 循环访问自定义分类对象的列表
- 循环访问自定义类的列表
- 如何简单地循环自定义比例