c - 将分数与按位运算相乘

时间:2015-03-26 01:02:05

标签: c bit-manipulation fractions

好吧所以我一直试图找出如何将分数(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个运算符。我只是寻求帮助解决问题的最佳方法。提前谢谢!

1 个答案:

答案 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.