要回答this question,我在github上阅读this source code,发现第二个功能有问题。
面临的挑战是编写C代码,在操作符和语言结构方面有各种限制来执行给定的任务。
BigInt
左移一个负值或一个移位值超出/*
* fitsShort - return 1 if x can be represented as a
* 16-bit, two's complement integer.
* Examples: fitsShort(33000) = 0, fitsShort(-32768) = 1
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 8
* Rating: 1
*/
int fitsShort(int x) {
/*
* after left shift 16 and right shift 16, the left 16 of x is 00000..00 or 111...1111
* so after shift, if x remains the same, then it means that x can be represent as 16-bit
*/
return !(((x << 16) >> 16) ^ x);
}
范围的数字有未定义的行为,右移一个负值是实现定义的,所以上面的解决方案是不正确的(虽然它可能是预期的溶液)。
这个问题的解决方案是否只假设32位二进制补码表示?
答案 0 :(得分:1)
以下仅假设2位补码至少包含16位:
int mask = ~0x7FFF;
return !(x&mask)|!(~x&mask);
使用15位常数;如果它太大,你可以用三个较小的常量来构造它,但这会将它推到8个运算符限制之上。
一种等效的写作方式:
int m = 0x7FFF;
return !(x&~m)|!~(x|m);
但它仍然有7个操作,所以int m = (0x7F<<8)|0xFF;
仍然会将它推到9.(我只是添加了它,因为我不认为我以前曾经使用过它!~
。)