76

Which is the simplest way to check if two integers have same sign? Is there any short bitwise trick to do this?

19 Answers19

243

What's wrong with

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

?

Rik
  • 28,507
  • 14
  • 48
  • 67
  • 33
    Um... Nothing... Sad that we all missed the simple solution. – Torlack Sep 16 '08 at 14:29
  • 1
    What about Signed zero. -0.0 vs Unsigned zero 0.0 – Ólafur Waage May 14 '11 at 13:24
  • 1
    @Ólafur: OP specified integers, not floats. – Nicholas Knight Jun 02 '11 at 13:45
  • 4
    This assumes that you want to consider 0 as being the same sign as a positive integer. – SpoonMeiser Mar 03 '16 at 10:43
  • @ÓlafurWaage At least in JavaScript, the following is true [`-0===+0`](http://ecma262-5.com/ELS5_HTML.htm#Section_11.9.6), so it's not an issue there. – Christoph Jun 01 '17 at 14:33
  • 2
    **Never settle for an accepted answer! Always be curious! Maybe it's time for SO, to reconsider the true meaning of an accepted answer. SO should modify the true meaning of accepted answer, so that the most relevant ones float on the top. Else, most lazy geeks like me don't even bother to scroll for alternatives.** – taurus05 Apr 27 '21 at 13:49
  • @taurus05 you can order answers by highest score or trending score. Even if you don't read down the bottom, in general others will and this should bring the new better answers to the top. Like this one has. – Fantastic Mr Fox Nov 02 '22 at 06:15
52

Here is a version that works in C/C++ that doesn't rely on integer sizes or have the overflow problem (i.e. x*y>=0 doesn't work)

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

Of course, you can geek out and template:

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

Note: Since we are using exclusive or, we want the LHS and the RHS to be different when the signs are the same, thus the different check against zero.

Torlack
  • 4,395
  • 1
  • 23
  • 24
39
(a ^ b) >= 0

will evaluate to 1 if the sign is the same, 0 otherwise.

MD XF
  • 7,860
  • 7
  • 40
  • 71
  • Oh, nice! :-) I'm surprised that I missed this one. The really nice thing about this solution is it doesn't depend upon a particular bit cardinality in the underlying integer representation. – Daniel Spiewak Sep 15 '08 at 21:09
  • 1
    This one results in the delightfully compact "xorl %edi, %esi; sets %al" on x86, only 6 bytes and two instructions. It's also an interesting case study as it's a concrete case where returning a 'bool' instead of an int produces dramatically better code. – John Meacham Jul 06 '14 at 08:13
  • @JohnMeacham : Wondering what you mean by 'it's a concrete case where returning a 'bool' instead of an int produces dramatically better code' – MK. May 19 '16 at 15:54
12

I would be wary of any bitwise tricks to determine the sign of integers, as then you have to make assumptions about how those numbers are represented internally.

Almost 100% of the time, integers will be stored as two's compliment, but it's not good practice to make assumptions about the internals of a system unless you are using a datatype that guarentees a particular storage format.

In two's compliment, you can just check the last (left-most) bit in the integer to determine if it is negative, so you can compare just these two bits. This would mean that 0 would have the same sign as a positive number though, which is at odds with the sign function implemented in most languages.

Personally, I'd just use the sign function of your chosen language. It is unlikely that there would be any performance issues with a calculation such as this.

SpoonMeiser
  • 19,918
  • 8
  • 50
  • 68
  • 1
    The C Standard Lib provides a signbit() function. Probably tough to beat the optimiser with any "bitwise tricks" of your own devising. –  Sep 15 '08 at 21:37
6

Assuming 32 bit ints:

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

Slightly more terse:

bool same = !((x ^ y) >> 31);
Patrick
  • 90,362
  • 11
  • 51
  • 61
  • 3
    Those two code examples should ALWAYS ALWAYS ALWAYS be preceded by a code comment please (in real life) – Jorge Córdoba Sep 15 '08 at 21:08
  • 4
    Oh, of course. In real life, I'd probably use something like same = Math.Sign(x) == Math.Sign(y). I just give evil bitwidily solutions when people ask for them. :D – Patrick Sep 15 '08 at 23:00
  • 1
    Um, this is not valid code... how do you expect `& >>` to work? – MD XF Oct 04 '17 at 01:30
  • It wasn't. I have no idea what I was thinking with that and sign 10 years ago. – Patrick Oct 04 '17 at 05:22
5

(integer1 * integer2) > 0

Because when two integers share a sign, the result of multiplication will always be positive.

You can also make it >= 0 if you want to treat 0 as being the same sign no matter what.

Benjamin Autin
  • 4,143
  • 26
  • 34
5

I'm not really sure I'd consider "bitwise trick" and "simplest" to be synonymous. I see a lot of answers that are assuming signed 32-bit integers (though it would be silly to ask for unsigned); I'm not certain they'd apply to floating-point values.

It seems like the "simplest" check would be to compare how both values compare to 0; this is pretty generic assuming the types can be compared:

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

If the signs are opposite, you get false. If the signs are the same, you get true.

Christoph
  • 50,121
  • 21
  • 99
  • 128
OwenP
  • 24,950
  • 13
  • 65
  • 102
4

Assuming twos complement arithmetic (http://en.wikipedia.org/wiki/Two_complement):

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

This can take as little as two instructions and less than 1ns on a modern processor with optimization.

Not assuming twos complement arithmetic:

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

This may require one or two extra instructions and take a little longer.

Using multiplication is a bad idea because it is vulnerable to overflow.

user10315
  • 61
  • 4
3

if (x * y) > 0...

assuming non-zero and such.

Yes - that Jake.
  • 16,725
  • 14
  • 70
  • 96
2

As a technical note, bit-twiddly solutions are going to be much more efficient than multiplication, even on modern architectures. It's only about 3 cycles that you're saving, but you know what they say about a "penny saved"...

Daniel Spiewak
  • 54,515
  • 14
  • 108
  • 120
1

branchless C version:

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

C++ template for integer types:

template <typename T> T sameSign(T a, T b) {
    return ~(a^b) & (1<<(sizeof(T)*8-1));
}
CAFxX
  • 28,060
  • 6
  • 41
  • 66
1

Just off the top of my head...

int mask = 1 << 31;
(a & mask) ^ (b & mask) < 0;
Daniel Spiewak
  • 54,515
  • 14
  • 108
  • 120
1

if (a*b < 0) sign is different, else sign is the same (or a or b is zero)

1

For any size of int with two's complement arithmetic:

#define SIGNBIT (~((unsigned int)-1 >> 1))
if ((x & SIGNBIT) == (y & SIGNBIT))
    // signs are the same
nyg
  • 2,380
  • 3
  • 25
  • 40
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
1

assuming 32 bit

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

... the answer if(x*y>0) is bad due to overflow

dpel
  • 1,954
  • 1
  • 21
  • 31
ugasoft
  • 3,778
  • 7
  • 27
  • 23
0

Better way using std::signbit as follows:

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

It also support other basic types (double, float, char etc).

ashiquzzaman33
  • 5,781
  • 5
  • 31
  • 42
0

Thinking back to my university days, in most machine representations, isn't the left-most bit of a integer a 1 when the number is negative, and 0 when it's positive?

I imagine this is rather machine-dependent, though.

Dana
  • 32,083
  • 17
  • 62
  • 73
0

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

if ( same_sign ) ... else ...

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");
    }
}