如何检查有符号整数是否为正?

时间:2010-09-16 22:49:16

标签: c bit-manipulation bitwise-operators

使用按位运算符,我想加法和减法,如何检查有符号整数是否为正(具体而言,不是负数而不是零)?我确信这个问题的答案非常简单,但它并没有找到我。

5 个答案:

答案 0 :(得分:5)

如果你真的想要int n的“严格肯定”谓词而不使用条件(假设是2的补码):

    如果-n严格为正,
  • n将设置符号(顶部)位,并且 n == INT_MIN除外 ~n;
  • 如果n严格为正,则
  • n == INT_MIN将设置符号位,或者0,并且在所有其他情况下清除包括 -n & ~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);
}