user4642421
user4642421

Reputation:

Why is the binary equivalent calculation getting incorrect?

I wrote the following program to output the binary equivalent of a integer taking(I checked that int on my system is of 4 bytes) it is of 4 bytes. But the output doesn't come the right. The code is:

#include<iostream>
#include<iomanip>
using namespace std;

void printBinary(int k){
    for(int i = 0; i <= 31; i++){
        if(k & ((1 << 31) >> i))
            cout << "1";
        else 
            cout << "0";
    }
}

int main(){
    printBinary(12);
}

Where am I getting it wrong?

Upvotes: 18

Views: 1597

Answers (3)

Yu Hao
Yu Hao

Reputation: 122453

The problem is in 1<<31. Because 231 cannot be represented with a 32-bit signed integer (range −231 to 231 − 1), the result is undefined [1].

The fix is easy: 1U<<31.


[1]: The behavior is implementation-defined since C++14.

Upvotes: 29

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726839

This expression is incorrect:

if(k & ((1<<31)>>i))

int is a signed type, so when you shift 1 31 times, it becomes the sign bit on your system. After that, shifting the result right i times sign-extends the number, meaning that the top bits remain 1s. You end up with a sequence that looks like this:

80000000 // 10000...00
C0000000 // 11000...00
E0000000 // 11100...00
F0000000 // 11110...00
F8000000
FC000000
...
FFFFFFF8
FFFFFFFC
FFFFFFFE // 11111..10
FFFFFFFF // 11111..11

To fix this, replace the expression with 1 & (k>>(31-i)). This way you would avoid undefined behavior* resulting from shifting 1 to the sign bit position.

* C++14 changed the definition so that shifting 1 31 times to the left in a 32-bit int is no longer undefined (Thanks, Matt McNabb, for pointing this out).

Upvotes: 8

Ziezi
Ziezi

Reputation: 6467

A typical internal memory representation of a signed integer value looks like:

enter image description here

The most significant bit (first from the right) is the sign bit and in signed numbers(like int) it represents whether the number is negative or not. When you shift additional bits sign extension is performed to preserve the number's sign. This is done by appending digits to the most significant side of the number.(following a procedure dependent on the particular signed number representation used).
In unsigned numbers the first bit from the right is just the MSB of the represented number, thus when you shift additional bits no sign extension is performed.

Note: the enumeration of the bits starts from 0, so 1 << 31 replaces your sign bit and after that every bit shift operation to the left >> results in sign extension. (as pointed out by @dasblinkenlight)

So, the simple solution to your problem is to make the number unsigned (this is what U does in 1U << 31) before you start the bit manipulation. (as pointed out by @Yu Hao)

For further reading see signed number representations and two's complement.(as it's the most common)

Upvotes: 4

Related Questions