C中两个函数的比较

时间:2013-12-06 13:02:36

标签: c

int r2 (int a, int b)
{
return (a + (1<<(b-1))) >>b;
}

int r3 (int a, int b)
{
 return (a + (1<<(b-1)) -1 -(a>>31)) >>b;
}
  1. 他们之间有什么区别?
  2. 在某种程度上使用额外操作可能有什么好处 它是在函数r3()?
  3. 中完成的

    这个问题在接受我的采访时被问到了。 我很容易扩展表达式,但我没有得到第二个问题的答案。

3 个答案:

答案 0 :(得分:3)

这两个函数都可以使用舍入进行右移。即它们将值a / pow(2,b)舍入为最接近的整数。

不同之处在于a / pow(2,b)的小数部分恰好是一半。在这种情况下,第一个函数将始终向上舍入,而第二个函数将向零舍入。

第一个函数向上舍入,因为(1<<(b-1)) / pow(2,b)为0.5,所以它基本上返回floor((a+0.5) / pow(2,b))

第二个函数向零舍入,因为a>>31对于正a为0或对于-1a(假设为32位二进制补码int s )。对于否定a-1 + (a>>31) == 0,它返回与第一个函数相同的值,即它将向上舍入为零。对于正a-1 + (a>>31) == -1,所以它会在向右移动之前减去一个,这将导致一半的小数值向下舍入。

答案 1 :(得分:1)

看起来这些函数试图提供舍入而不是截断,以便将正数a除以2除以幂b。 如果你为面试官扩展了这些功能,我相信你已经向他解释了2件事的力量。

(希望你没有像我那样对这些功能嗤之以鼻,否则你可能没有得到这份工作。)
我会告诉他,这些功能在他们围绕* .5分区结果的方式上有所不同,为了支持我的陈述我会向他展示3个例子:

a = 13,b = 3:r2 =&gt; 2,r3 =&gt; 2:13/2 ^ 3 = 1.625
a = 12,b = 3:r2 =&gt; 2,r3 =&gt; 1:12/2 ^ 3 = 1.5
a = 11,b = 3:r2 =&gt; 1,r3 =&gt; 1:11/2 ^ 3 = 1.375

(我不会强调如果你能够将这些内容扩展到那些应该已经足够的话,那么就不会在面试中得到那么多。看起来他只是想向你展示他的“疯狂的技巧”。)

答案 2 :(得分:1)

1.他们之间有什么区别?

两者都以2的幂进行除法,并将结果舍入到最近(如果b在小范围之外,则用UB)。 r2轮次绑定。 r3将关系转向0。

2.在函数r3()中完成使用额外操作的优势是什么?

r3执行类似int除法的舍入。 int除法截断为0。

注意:随着64位int的出现以及使用16位int的嵌入式处理器的兴起,对31进行硬编码是有问题的编码。应该使用类似a>>(sizeof(int) *CHAR_BIT - 1)的内容而不是a>>31

对我来说,这是第一件突出的事情。通过了解公司的市场,它提出了一个机会来展示这种狭隘的C观点如何对公司产生负面影响。
超越回答这个问题。考虑问题的适用性。