14

I want to be able to access the sign bit of a number in C++. My current code looks something like this:

int sign bit = number >> 31;

That appears to work, giving me 0 for positive numbers and -1 for negative numbers. However, I don't see how I get -1 for negative numbers: if 12 is

0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1100

then -12 is

1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0011

and shifting it 31 bits would make

0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001

which is 1, not -1, so why do I get -1 when I shift it?

  • possible duplicate of [Absolute Beginner's Guide to Bit Shifting?](http://stackoverflow.com/questions/141525/absolute-beginners-guide-to-bit-shifting) – msw Jun 08 '10 at 22:07
  • int sign_bit = (int)(number > 0); – aviraldg Jun 08 '10 at 22:08
  • 5
    For [two's complement](http://en.wikipedia.org/wiki/Two%27s_complement#Complement_of_a_positive_number) (which most modern systems use), your -12 is wrong. It should end 0100. – Matthew Flaschen Jun 08 '10 at 22:13

9 Answers9

33

What about this?

int sign = number < 0;

Noctis Skytower
  • 21,433
  • 16
  • 79
  • 117
16

The result of right-shifting a negative number in C++ is implementation-defined. So, no one knows what right-shifting your -12 should get on your specific platform. You think it should make the above (1), while I say that it can easily produce all-ones pattern, which is -1. The latter is called sign-extended shifting. In sign-extended shifting the sign bit is copied to the right, but never shifted out of its place.

If all you are interested in is the value of the sign bit, then stop wasting time trying to use bitwise operations, like shifts etc. Just compare your number to 0 and see whether it is negative or not.

Neil G
  • 32,138
  • 39
  • 156
  • 257
AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • 1
    This is a really old post but I just saw this while looking for something else. I generally agree with what you are saying here. But there are some assumptions that he made in his question that might have contributed to outcome of his code. This can be done arch independently using bit shifting or just using a bit-mask to check the sign bit. – AR5HAM Dec 24 '14 at 02:13
  • This doesn't distinguish -0.0 from +0.0. You need to access the sign bit for that. See John's answer. – Neil G May 09 '16 at 23:58
  • @NeilG Based on the text in the question, it seems to me to be asking about integers . – M.M May 10 '16 at 01:35
  • @m.m Oh!! I got fooled by the other answers and didn't read carefully. – Neil G May 10 '16 at 01:36
  • I realise this is an old topic, but could the latter situation be avoided by bitwise & 1? – nitronoid Jul 31 '17 at 20:07
  • @nitronoid: Not sure what you mean. – AnT stands with Russia Jul 31 '17 at 20:10
  • @AnT If the result of the shift produced an "all-ones pattern", but the desired output was for those 1's to be 0's, couldn't I just &1 to set all bits to zero except for the least significant. Not suggesting this is a better solution, but just asking if it would work? – nitronoid Jul 31 '17 at 21:30
9

Because you are shifting signed integer. Cast the integer to unsigned:

int sign_bit = ((unsigned int)number) >> 31;
Paya
  • 5,124
  • 4
  • 45
  • 71
8

You can use cmath library

#include <cmath>

and use it like

std::cout << std::signbit(num);

This function get a float value as input and a bool value as output.

true for negative
false for positive

for instance

std::cout << std::signbit(1);

will give you a 0 as output (false)

but while using this function you have to be careful about zero

std::cout << std::signbit(-0.0);  // 512 (true)
std::cout << std::signbit(+0.0);  // 0   (false)

The output of this lines are not the same.

To remove this problem you can use:

float x = +0.01;
std::cout << (x >= 0 ? (x == 0 ? 0 : 1) : -1);

which give:

 0 for 0
 1 for positive
-1 for negative
Hadi Rasekh
  • 2,622
  • 2
  • 20
  • 28
4

For integers, test number < 0.

For floating point numbers, you may also want take into account the fact that zero has a sign. That is, there exists a -0.0 which is distinct from +0.0. To distinguish the two, you want to use std::signbit.

John
  • 29,546
  • 11
  • 78
  • 79
3

The >> operator is performing an arithmetic shift, which retains the sign of the number.

LukeH
  • 263,068
  • 57
  • 365
  • 409
  • 4
    No. What kind of shift is performed by `>>` operator is implementation-defined. Could be any kind of shift. – AnT stands with Russia Jun 08 '10 at 22:10
  • 1
    @AndreyT: I said "the `>>` operator is performing an arithmetic shift", and that's exactly what it is doing in this case, judging by the OP's description. Notice that I *did not* say "the `>>` operator always performs an arithmetic shift" or anything like that. Perhaps I should have been more explicit, but either way, I don't think my answer deserves a downvote. – LukeH Jun 09 '10 at 01:01
  • 3
    @Downvoters: Please justify yourselves. I explained *exactly* what the OP's problem is. I didn't make any broad claims like "the `>>` operator always performs an arithmetic shift"; I explained *exactly* what the `>>` operator is doing *in this particular case*. – LukeH Nov 17 '11 at 09:42
1
bool signbit(double x)
{
    return 1.0/x != 1.0/fabs(x);
}

My solution that supports +/-0.

quietk
  • 11
  • 2
0

You could do the following:

int t1 = -12;
unsigned int t2 = t1;
t2 = t2>>31;
cout<<t2;

This will work fine for all implementations of c++.

-1
bool signbit(double x)
{
    return (__int64)x & 0x8000000000000000LL != 0LL;
}

bool signbit(float x)
{
    return (__int32)x & 0x80000000 != 0;
}
SamY
  • 1