我在这个网站上看到了这个功能的其他几个实现,但是我很好奇是否有人可以帮我弄清楚为什么这个实现不起作用:
//fitsBits: return 1 if x can be represented as an n-bit, two's complement integer.
//1<=n<=32
//Examples: fitsBits(5,3)=0, fitsBits(-4,3)=1
//legal ops: ! ~ & ^ | + << >>
//Max ops: 15
int fitsBits(int x, int n) {
int mask = ~(1<<31);
return !(((x>>1)&mask)>>(~(~n+2)+1));
}
所以你可以稍微遵循我的逻辑,我向右移动x,这可能会暴露额外的1(算术移位)。所以我创建了一个掩码,以确保它在移动x的其余部分之前变为零。最初我需要向右移动x次,如果有任何剩余的1,则表示x不符合n位。由于我已将x向右移动一位,我现在需要将其移动n-1次。
我得到的结果是:
ERROR: Test fitsBits(2147483647[0x7fffffff],31[0x1f]) failed...
...Gives 1[0x1]. Should be 0[0x0]
答案 0 :(得分:0)
你所写的内容看起来像C,其中-ve数的右移是“实现定义的”,所以可能是也可能不是算术移位。 (对于左移,情况甚至更糟,-ve值的结果是未定义的。)所以,最好是做所有无符号的琐事。
对于2的补码,n位...... a + ve数必须从位(n-1)向上全'0',而-ve数必须全为'1'...因此,在C假设所有无符号32位整数(没有填充!)......
m = UINT_MAX << (n - 1) ; // bits from n-1 upwards
q = - (x >> 31) ; // all sign bits, assuming 32bit integers
return ((x ^ q) & m) == 0 ;
稍后添加......
...我承认我没有努力尝试找出你的代码:
int fitsBits(int x, int n)
{
int mask = ~(1<<31);
return !(((x>>1)&mask)>>(~(~n+2)+1));
}
可能正在努力(考虑到转移int
值的困难)。但是,假设mask
最终为0x7FFFFFFF
,而(x>>1)
是简单转换或算术转换,那么:
(x>>1)&mask
是1的简单转换,如((unsigned)x)>>1
~n+2
~n+1+1
是-n+1
(因为我们假设是2的补码)
且~(~n+2)+1
-(~n+2)
-(-n+1)
为n-1
所以,(((x>>1)&mask)>>(~(~n+2)+1))
是(((unsigned)x)>>1)>>(n-1)
(鼓声)......
... ((unsigned)x)>>n
...这是为了将x
存储在n
位字段中而被丢弃的所有位。
如果您想测试x
是否适合无符号 n
位字段,那么(((unsigned)x)>>n) == 0
就可以了。
要测试签名 x
是否适合签名的 n
位字段,您需要担心{{1}的值},必须为零或((unsigned)x)>>(n-1)
,具体取决于0xFFFFFFFF>>(n-1)
的符号。
(我注意到,顺便提一下,要求是x
...如果1<=n<=32
,我们只有符号位,所以我们可以表示-1..0范围内的数字,看起来很奇怪,但仍然是正确的。)