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

有帮助吗?

解决方案

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

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

当然,你可以geek out和模板:

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

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

其他提示

出了什么问题

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

?

(a ^ b) >= 0

如果符号相同,则计算结果为 1,否则计算结果为 0。

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

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

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

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

假设 32 位整数:

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

稍微简洁一点:

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

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

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

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

如果符号相反,则结果为假。如果迹象相同,则说明正确。

(整数 1 * 整数 2) > 0

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

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

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

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

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

不假设二进制补码算术:

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

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

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

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

假设非零等等。

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

就在我头顶上...

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

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

对于任意大小的 int 进行二进制补码算术:

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

假设32位

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

...答案 if(x*y>0) 由于溢出而损坏

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

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

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

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

如果(相同的符号)...别的 ...

更好的使用方式 std::符号位 如下:

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

它还支持其他基本类型(double, float, char ETC)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top