使用按位运算符,我想加法和减法,如何检查有符号整数是否为正(具体而言,不是负数而不是零)?我确信这个问题的答案非常简单,但它并没有找到我。
答案 0 :(得分:5)
如果你真的想要int n
的“严格肯定”谓词而不使用条件(假设是2的补码):
-n
严格为正,n
将设置符号(顶部)位,并且 n == INT_MIN
除外 ~n
; n
严格为正,则n == INT_MIN
将设置符号位,或者0,并且在所有其他情况下清除包括 -n & ~n
; int strictly_positive = (unsigned)(-n & ~n) >> ((sizeof(int) * CHAR_BIT) - 1);
将设置符号位,并在所有其他情况下清除。应用无符号转换将其转换为0/1答案:
-n
编辑:正如咖啡馆在评论中指出的那样,n == INT_MIN
会在-ftrapv
时导致溢出(仍假设为2的补码)。在这种情况下,C标准允许程序失败(例如,您可以使用带有n
选项的GCC为已签名的溢出启用陷阱)。将unsigned u = (unsigned)n;
int strictly_positive = (-u & ~u) >> ((sizeof(int) * CHAR_BIT) - 1);
转换为无符号修复了问题(无符号算术不会导致溢出)。所以改进是:
{{1}}
答案 1 :(得分:3)
检查最重要的位。 0为正,1为负。
答案 2 :(得分:3)
如果你不能使用明显的比较运算符,那么你必须更加努力:
int i = anyValue;
if (i && !(i & (1U << (sizeof(int) * CHAR_BIT - 1))))
/* I'm almost positive it is positive */
第一项检查该值不为零;第二个检查该值没有设置前导位。这应该适用于2的补码,1的补码或符号幅度的整数。
答案 3 :(得分:1)
考虑如何表示签名。通常用二进制或一个简单的符号位完成 - 我认为这两个都可以用简单的逻辑来检查。
答案 4 :(得分:0)
检查是否为0且最高有效位为0,如:
int positive(int x) {
return x && (x & 0x80000000);
}