使用按位运算符确定Int是否适合C的缩写

时间:2019-02-07 02:27:33

标签: c binary int bit-manipulation

我的任务是制作一个函数,该函数返回int x是否适合C的缩写(如果满足,则返回1,否则返回0)。通常,这是一个相当简单的解决方案,但是我只能使用以下按位运算符: 〜&^ | + << >>。

还有更多规则:

  • 我最多只能使用8个这些运算符。

  • 不包含任何外部库。

  • 不允许我使用任何条件语句(所以不能使用ifs,whiles, 等)。

  • 我只能使用int类型的变量,而我不能 定义常量,例如0x0000ffff。但是,我可以使用0x0和0xff。

  • 可以安全地假设int是32位,而short是16位。

我了解这些运算符的基本功能,但对实现逻辑感到困惑。有什么想法吗?

2 个答案:

答案 0 :(得分:3)

假设两个补码(算术右移,舍弃溢出位的左移)和32位max_limit,则:

int
当且仅当x<<16>>16 ^ x 符合16位x时,

为零。

由于要求我们为不适合返回0,为不适合返回1,因此我们可以返回:

short

证明:

如果! (x<<16>>16 ^ x) 适合x,则short•2 16 适合x,因此int产生没有溢出,并且x<<16恢复x<<16>>16(由于算术右移仅去除零是有效的除法运算,没有余数),之后x为零。

如果x ^ x短了,则x溢出(我们假设会导致丢弃高位)。此外,它的值是x<<16对某些短的y<<16产生的值之一。然后y必须产生与x<<16>>16相同的值y<<16>>16,该值不同于y,因此x不能为零。

答案 1 :(得分:0)

假设2个补码,您最初的想法是测试15位以外的所有前导位全为0或全为1。

11111111 11111111 1xxxxxxx xxxxxxxx /* for negative 16 bits int */
00000000 00000000 0xxxxxxx xxxxxxxx /* for positive 16 bits int */

假设算术右移,您可以右移15位以消除未知位,那么仅剩1或0(如果适合15位)

因此x>>15应该为0或-1。
如果为0,则!(x >> 15)为true。
如果为-1,则!(〜(x >> 15))为true。
因此,您可以测试!(x>>15) | !(~(x>>15))
或者,您也可以这样写:!(x>>15) | !(~x>>15)

请注意,上面的表达式不假定x为32位,并且也可以用于测试int64是否适合int16 ...

还有很多其他方法...
由于您也可以使用+,因此(x>>15)+1为0或1。
然后,您可以使用((x>>15)+1)>>1清除最后一位。
如果以上表达式全为0(false),x确实适合16位整数,因此您需要:

! (((x>>15)+1)>>1)

您可以根据自己的需要找到更多的表达方式...