好吧所以我一直试图找出如何将分数(3/4)乘以c中的有符号整数。挑战是仅使用逻辑运算符(!〜& ^ | +<<>>>)而没有(if语句,循环等)并且使用最多12个逻辑运算符。目标是完全模仿以下表达式(x * 3/4)。现在我已经看了其他类似问题的问题(只是有不同的分数)但是那些解决方案有超过12个运算符使用。我已经尝试过简化它们,但如果没有解决方案不能正常工作,似乎无法做到这一点。以下是5/8问题的解决方案:
int s = -((num >> 31) & 1); // sign bit as -1 or 0
int n = (num ^ s) - s; // twos complement if negative
int x = n >> 3; // divide by 8
x = (x << 2) + x; // multiply by 5; no overflow yet since 5/8 is less than one
int y = n & 7; // the bits we shifted out
y = (y << 2) + y; // multiply by 5; no overflow
return (s ^ (x + (y >> 3))) - s; // the two pieces and complemented back
我不确定上面的方法是否正确,因为我插入-2并手动完成并得到-3回来。应该是-1,因为-2 *(5/8)= -1.25
我原来想解决这个问题就是要检查并溢出。这是因为一个简单的程序,如:
x = (x<<1) + x;
x = X>>2;
溢出情况下的会导致答案被+1关闭。为了解决这个问题,我认为我必须将限制除以3并检查并查看乘以的整数是否大于715827882或-715827882。如果数字更大,则从比较中获得1并将其添加到最终结果中,或者如果小于,则获得0并将0添加到最终结果。我觉得这种方式很难实现,没有if语句,并且它可能使用超过12个运算符。我只是寻求帮助解决问题的最佳方法。提前谢谢!
答案 0 :(得分:3)
你的想法是:
x=(x<<1)+x; // do x=x*3
x=x>>2; // do x=x/4
这可能会溢出,因为x
首先保持较大的值。这会有用吗?
x=x-(x>>2); // do x=x-x/4, equal to 3/4
当然,因为x>>2
抛弃了最低位,所以结果被截断了。如果你需要截断,这是错误的,你应该使用加法:
x=(x>>1)+((x+1)>>2); // x=x/2+x/4
编辑:您需要(x+1)>>2
以避免双截断结果丢失,例如x = 7.