71

检查两个整数是否具有相同符号的最简单方法是什么?是否有任何简短的按位技巧来做到这一点?

4

19 回答 19

227

有什么问题

return ((x<0) == (y<0));  

?

于 2008-09-15T22:06:19.607 回答
52

这是一个在 C/C++ 中工作的版本,它不依赖于整数大小或存在溢出问题(即 x*y>=0 不起作用)

bool SameSign(int x, int y)
{
    return (x >= 0) ^ (y < 0);
}

当然,你可以geek out和template:

template <typename valueType>
bool SameSign(typename valueType x, typename valueType y)
{
    return (x >= 0) ^ (y < 0);
}

注意:由于我们使用异或,当符号相同时,我们希望 LHS 和 RHS 不同,因此对零进行不同的检查。

于 2008-09-15T21:12:14.310 回答
34
(a ^ b) >= 0

如果符号相同,将评估为 1,否则评估为 0。

于 2008-09-15T21:06:18.160 回答
12

我会警惕任何确定整数符号的按位技巧,因为你必须假设这些数字在内部是如何表示的。

几乎 100% 的情况下,整数将作为二进制补码存储但除非您使用保证特定存储格式的数据类型,否则对系统内部进行假设并不是一个好习惯。

在二进制的恭维中,您可以检查整数中的最后(最左边)位以确定它是否为负,因此您可以只比较这两个位。这意味着 0 将与正数具有相同的符号,这与大多数语言中实现的符号函数不一致。

就个人而言,我只会使用您选择的语言的符号功能。这样的计算不太可能出现任何性能问题。

于 2008-09-15T21:06:48.673 回答
6

假设 32 位整数:

bool same = ((x ^ y) >> 31) != 1;

稍微简洁一点:

bool same = !((x ^ y) >> 31);
于 2008-09-15T21:01:24.273 回答
5

(整数 1 * 整数 2) > 0

因为当两个整数共用一个符号时,相乘的结果总是正的。

如果您无论如何都想将 0 视为相同的符号,也可以使其 >= 0。

于 2008-09-15T21:01:46.470 回答
5

我不确定我是否会认为“按位技巧”和“最简单”是同义词。我看到很多假设有符号 32 位整数的答案(尽管要求无符号整数会很愚蠢);我不确定它们是否适用于浮点值。

似乎“最简单”的检查是比较两个值与 0 的比较;假设可以比较类型,这是非常通用的:

bool compare(T left, T right)
{
    return (left < 0) == (right < 0);
}

如果符号相反,你就错了。如果符号相同,则为真。

于 2008-09-15T21:25:30.563 回答
4

假设二进制补码算术(http://en.wikipedia.org/wiki/Two_complement):

inline bool same_sign(int x, int y) {
    return (x^y) >= 0;
}

在经过优化的现代处理器上,这只需两条指令和不到 1ns 的时间。

不假设二进制补码算术:

inline bool same_sign(int x, int y) {
    return (x<0) == (y<0);
}

这可能需要一两个额外的指令,并且需要更长的时间。

使用乘法是个坏主意,因为它容易溢出。

于 2008-09-15T22:45:33.757 回答
3

如果 (x * y) > 0...

假设非零等。

于 2008-09-15T20:58:17.320 回答
2

作为技术说明,即使在现代架构上,位复杂的解决方案也将比乘法更有效。您只节省了大约 3 个周期,但您知道他们所说的“节省一分钱”...

于 2008-09-15T21:04:56.680 回答
1

就在我的头顶...

int mask = 1 << 31;
(a & mask) ^ (b & mask) < 0;
于 2008-09-15T20:59:37.223 回答
1

if (a*b < 0) 符号不同,否则符号相同(或 a 或 b 为零)

于 2008-09-15T21:00:12.420 回答
1

对于具有二进制补码算术的任何大小的 int:

#define SIGNBIT (~((unsigned int)-1 >> 1))
if ((x & SIGNBIT) == (y & SIGNBIT))
    // signs are the same
于 2008-09-15T21:15:32.740 回答
1

假设 32 位

if(((x^y) & 0x80000000) == 0)

if(x*y>0)...由于溢出,答案很糟糕

于 2008-09-15T21:18:07.930 回答
1

无分支 C 版本:

int sameSign(int a, int b) {
    return ~(a^b) & (1<<(sizeof(int)*8-1));
}

整数类型的 C++ 模板:

template <typename T> T sameSign(T a, T b) {
    return ~(a^b) & (1<<(sizeof(T)*8-1));
}
于 2011-06-02T14:18:52.097 回答
0

回想我的大学时代,在大多数机器表示中,整数的最左边不是数字为负数时为 1,为正数时为 0 吗?

不过,我想这是相当依赖机器的。

于 2008-09-15T21:01:27.203 回答
0

int same_sign = !( (x >> 31) ^ (y >> 31) );

if (same_sign) ... 否则 ...

于 2008-09-15T21:04:14.593 回答
0

使用std::signbit的更好方法如下:

std::signbit(firstNumber) == std::signbit(secondNumber);

它还支持其他基本类型(double,floatchar)。

于 2015-12-01T22:16:58.890 回答
0
#include<stdio.h>

int checksign(int a, int b)
{
 return (a ^ b); 
}

void  main()
{
    int a=-1, b = 0;

    if(checksign(a,b)<0)
    {
        printf("Integers have the opposite sign");
    }
    else
    {
        printf("Integers have the same sign");
    }
}
于 2021-05-22T13:20:21.853 回答