it-swarm.cn

检查两个整数是否有相同符号的最简单方法?

检查两个整数是否具有相同符号的最简单方法是什么?这有什么简单的按位技巧吗?

60
Gerber

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

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

当然,你可以嘲笑和模板:

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

注意:由于我们使用exclusive或者,我们希望LHS和RHS在符号相同时不同,因此不同的检查为零。

47
Torlack

怎么了?

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

202
Rik
(a ^ b) >= 0

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

23
Chris Jobson

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

几乎100%的时间,整数将被存储为 两个恭维 ,但除非您使用的是保证特定存储格式的数据类型,否则对系统内部进行假设并不是一种好的做法。

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

就个人而言,我只是使用您所选语言的符号功能。像这样的计算不太可能存在任何性能问题。

12
SpoonMeiser

假设32位整数:

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

稍微简洁一点:

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

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

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

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

如果标志相反,你会得到假的。如果标志相同,你就会成真。

5
OwenP

(integer1 * integer2)> 0

因为当两个整数共享一个符号时,乘法的结果将始终为正。

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

4
Benjamin Autin

假设二进制补码算术( 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);
}

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

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

4
user10315

if(x * y)> 0 ...

假设非零等等。

3
Yes - that Jake.

作为一个技术说明,即使在现代架构上,比特冗余的解决方案也会比乘法更有效。你节省的时间只有3个左右,但是你知道他们对“便士保存”的看法......

2
Daniel Spiewak

无分支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));
}
1
CAFxX

就在我的头顶......

int mask = 1 << 31;
(a & mask) ^ (b & mask) < 0;
1
Daniel Spiewak

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

#define SIGNBIT (~((unsigned int)-1 >> 1))
if ((x & SIGNBIT) == (y & SIGNBIT))
    // signs are the same
1
Mark Ransom

假设32位

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

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

1
ugasoft

如果(a * b <0)符号不同,则其他符号相同(或者a或b为零)

0
dogfish

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

不过,我想这可能与机器有关。

0
Dana

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

if(same_sign)... else ...

0
andrew

更好地使用 std :: signbit 如下:

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

它还支持其他基本类型(doublefloatchar等)。

0
ashiquzzaman33