检查两个整数是否具有相同符号的最简单方法是什么?是否有任何简短的按位技巧来做到这一点?
19 回答
有什么问题
return ((x<0) == (y<0));
?
这是一个在 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 不同,因此对零进行不同的检查。
(a ^ b) >= 0
如果符号相同,将评估为 1,否则评估为 0。
我会警惕任何确定整数符号的按位技巧,因为你必须假设这些数字在内部是如何表示的。
几乎 100% 的情况下,整数将作为二进制补码存储,但除非您使用保证特定存储格式的数据类型,否则对系统内部进行假设并不是一个好习惯。
在二进制的恭维中,您可以检查整数中的最后(最左边)位以确定它是否为负,因此您可以只比较这两个位。这意味着 0 将与正数具有相同的符号,这与大多数语言中实现的符号函数不一致。
就个人而言,我只会使用您选择的语言的符号功能。这样的计算不太可能出现任何性能问题。
假设 32 位整数:
bool same = ((x ^ y) >> 31) != 1;
稍微简洁一点:
bool same = !((x ^ y) >> 31);
(整数 1 * 整数 2) > 0
因为当两个整数共用一个符号时,相乘的结果总是正的。
如果您无论如何都想将 0 视为相同的符号,也可以使其 >= 0。
我不确定我是否会认为“按位技巧”和“最简单”是同义词。我看到很多假设有符号 32 位整数的答案(尽管要求无符号整数会很愚蠢);我不确定它们是否适用于浮点值。
似乎“最简单”的检查是比较两个值与 0 的比较;假设可以比较类型,这是非常通用的:
bool compare(T left, T right)
{
return (left < 0) == (right < 0);
}
如果符号相反,你就错了。如果符号相同,则为真。
假设二进制补码算术(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);
}
这可能需要一两个额外的指令,并且需要更长的时间。
使用乘法是个坏主意,因为它容易溢出。
如果 (x * y) > 0...
假设非零等。
作为技术说明,即使在现代架构上,位复杂的解决方案也将比乘法更有效。您只节省了大约 3 个周期,但您知道他们所说的“节省一分钱”...
就在我的头顶...
int mask = 1 << 31;
(a & mask) ^ (b & mask) < 0;
if (a*b < 0) 符号不同,否则符号相同(或 a 或 b 为零)
对于具有二进制补码算术的任何大小的 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)
...由于溢出,答案很糟糕
无分支 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,为正数时为 0 吗?
不过,我想这是相当依赖机器的。
int same_sign = !( (x >> 31) ^ (y >> 31) );
if (same_sign) ... 否则 ...
使用std::signbit的更好方法如下:
std::signbit(firstNumber) == std::signbit(secondNumber);
它还支持其他基本类型(double
,float
等char
)。
#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");
}
}