基于最大值的换行/溢出数的算法
Posted
技术标签:
【中文标题】基于最大值的换行/溢出数的算法【英文标题】:An algorithm to wrap/overflow number based on max value 【发布时间】:2013-01-10 15:32:35 【问题描述】:有人来挑战吗?我正在寻找一种有效的算法来实现固定最大值的数字的换行/溢出行为。
说,最大可能的数值定义为:
#define MAX_NUMBER_VALUE 100
还有一个函数translate
,它接受一个带符号的 32 位或 64 位整数值,并使用 MAX_NUMBER_VALUE 常量“环绕”它:
int_fast8_t translate(int_fast32_t value)
if (abs(value) > MAX_NUMBER_VALUE)
return ...; // This!
return value;
预期的输入和输出:
translate(55) => 55
translate(100) => 100
translate(101) => -100
translate(102) => -99
translate(200) => -1
translate(202) => 1
translate(300) => 99
translate(-40) => -40
translate(-100) => -100
translate(-101) => 100
translate(-102) => 99
translate(-200) => 1
translate(-201) => 0
...
值围绕数字“走动”,就好像它是一个圆形行星。这看起来确实类似于 C/C++ 处理 int 溢出条件的方式。我想知道是否有一种快速有效的方法来实现这种包装?像移位或其他按位运算一样?
【问题讨论】:
您是在描述%
运算符吗?
你基本上需要对MAX_NUMBER_VALUE*2 - 1
做一个模数...
【参考方案1】:
听起来您只是在描述%
运算符,并对负数进行了一些仔细的处理。
【讨论】:
您应该详细说明这种“小心处理负数” - 这是我认为问题的重要方面。我怀疑答案是否会非常有用。 是的,我很清楚模运算符在这里很可能是不可避免的。不过,我想知道是否有像位移一样的替代方法。 @Sim:对于MAX
的任意值,并非如此。您总是可以定义一个庞大的查找表,但由于缓存性能糟糕,这可能不会更快!
@OliCharlesworth:谢谢。我只是好奇如果我的 MAX_NUMBER_VALUE 可以表示为 2^n,我将如何编写移位包装?
@Sim:假设 2 的补码,那么你应该可以只做x &= (2*n-1); if (x >= n) x -= 2*n;
。【参考方案2】:
int_fast8_t translate(int_fast32_t value)
return sgn(value)*( (abs(value)+MAX)%(2*MAX+1)-MAX )
应该这样做,假设为 int_fast32_t
类型定义了模块化划分
已编辑以包括处理负数,但现在看起来有点混乱。有关 sgn(x) 的智能实现,请参阅this
【讨论】:
您确定要将输出范围设为闭合区间 [-MAX_NUMBER_VALUE, MAX_NUMBER_VALUE]?使用半开区间 [-MAX_NUMBER_VALUE, MAX_NUMBER_VALUE) 或 (-MAX_NUMBER_VALUE, MAX_NUMBER_VALUE] 会更自然 谢谢,但我认为这不会包含负数,比如 -101:(-101+100)%(2*100+1)-100 = -101
。
当然,抱歉。我应该注意之前关于“小心处理负数”的评论
要么我的数学是错误的,要么它仍然没有为负数换行:-101 => -1*(101+100)%(2*100+1)-100 = -100
! :)【参考方案3】:
只要您的input + MAX_VALUE
小于相关整数类型的最大值,我认为您可以使用它,甚至不需要初始abs
检查:
return ((input + MAX_VALUE) % (MAX_VALUE * 2 + 1)) - MAX_VALUE;
【讨论】:
nrussell 之前曾建议过这个,但是这不会包含负数,比如 -101:(-101+100)%(100*2+1)-100 = -101
以上是关于基于最大值的换行/溢出数的算法的主要内容,如果未能解决你的问题,请参考以下文章
截止目前为止,我遇到的最难的一道算法题:计算相邻两个数的最大差值
截止目前为止,我遇到的最难的一道算法题:计算相邻两个数的最大差值