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

发布于 2024-09-19 12:45:50 字数 78 浏览 4 评论 0原文

使用按位运算符以及我想的加法和减法,如何检查有符号整数是否为正(具体来说,不是负数也不是零)?我确信这个问题的答案非常简单,但我就是想不出来。

Using bitwise operators and I suppose addition and subtraction, how can I check if a signed integer is positive (specifically, not negative and not zero)? I'm sure the answer to this is very simple, but it's just not coming to me.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

暮倦 2024-09-26 12:45:50

如果您确实想要 int n 的“严格为正”谓词而不使用条件(假设 2 的补码):

  • -n 将设置符号(顶部)位,如果 < code>n 严格为正数,并且在所有其他情况下都是明确的,除了 n == INT_MIN
  • 如果n严格为正数或0,则~n将设置符号位,并在所有其他情况下清除包括 n = = INT_MIN
  • ...所以 -n &如果 n 严格为正,则 ~n 将设置符号位,并在所有其他情况下清除。

应用无符号移位将其变成 0 / 1 答案:

int strictly_positive = (unsigned)(-n & ~n) >> ((sizeof(int) * CHAR_BIT) - 1);

编辑:正如 caf 在评论中指出的那样,当 n == 时 -n 会导致溢出INT_MIN(仍然假设 2 的补码)。 C 标准允许程序在这种情况下失败(例如,您可以使用带有 -ftrapv 选项的 GCC 启用有符号溢出陷阱)。将 n 转换为 unsigned 可解决该问题(无符号算术不会导致溢出)。因此,改进将是:

unsigned u = (unsigned)n;
int strictly_positive = (-u & ~u) >> ((sizeof(int) * CHAR_BIT) - 1);

If you really want an "is strictly positive" predicate for int n without using conditionals (assuming 2's complement):

  • -n will have the sign (top) bit set if n was strictly positive, and clear in all other cases except n == INT_MIN;
  • ~n will have the sign bit set if n was strictly positive, or 0, and clear in all other cases including n == INT_MIN;
  • ...so -n & ~n will have the sign bit set if n was strictly positive, and clear in all other cases.

Apply an unsigned shift to turn this into a 0 / 1 answer:

int strictly_positive = (unsigned)(-n & ~n) >> ((sizeof(int) * CHAR_BIT) - 1);

EDIT: as caf points out in the comments, -n causes an overflow when n == INT_MIN (still assuming 2's complement). The C standard allows the program to fail in this case (for example, you can enable traps for signed overflow using GCC with the-ftrapv option). Casting n to unsigned fixes the problem (unsigned arithmetic does not cause overflows). So an improvement would be:

unsigned u = (unsigned)n;
int strictly_positive = (-u & ~u) >> ((sizeof(int) * CHAR_BIT) - 1);
作死小能手 2024-09-26 12:45:50

检查最高有效位。 0 为正,1 为负。

Check the most significant bit. 0 is positive, 1 is negative.

月下凄凉 2024-09-26 12:45:50

如果你不能使用明显的比较运算符,那么你必须更加努力:

int i = anyValue;
if (i && !(i & (1U << (sizeof(int) * CHAR_BIT - 1))))
    /* I'm almost positive it is positive */

第一项检查值是否不为零;第二个检查该值是否没有设置前导位。这应该适用于 2 的补码、1 的补码或符号数值整数。

If you can't use the obvious comparison operators, then you have to work harder:

int i = anyValue;
if (i && !(i & (1U << (sizeof(int) * CHAR_BIT - 1))))
    /* I'm almost positive it is positive */

The first term checks that the value is not zero; the second checks that the value does not have the leading bit set. That should work for 2's-complement, 1's-complement or sign-magnitude integers.

画尸师 2024-09-26 12:45:50

考虑如何表示符号。通常它是用补码或一个简单的符号位来完成的 - 我认为这两者都可以用简单的逻辑与来检查。

Consider how the signedness is represented. Often it's done with two's-complement or with a simple sign bit - I think both of these could be checked with a simple logical and.

何以畏孤独 2024-09-26 12:45:50

检查它不为 0 并且最高有效位为 0,如下所示:

int positive(int x) {
   return x && (x & 0x80000000);
}

Check that is not 0 and the most significant bit is 0, something like:

int positive(int x) {
   return x && (x & 0x80000000);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文