Signed and Unsigned Integers

Hi there all, I am a beginner to C++ and am struggling on grasping a concept.

I am running this script which was meant to help me understand the difference between the way that signed and unsigned integers are interpreted by C++.

#include <iostream>
using namespace std;

int main()
{
short int i;
int j;
j = 60000;
i = j;
cout << i << " " << j;

return 0;
}


which outputs "-5536 60000"

I understand that the ranges are different but why is the signed short integer represented as -5536? I can't wrap my mind around this, any light on this subject would be appreciated.

Thanks

The thing is that a number is represented by a constant number of digits. For example, lets take a number and represent it in two decimal digits.

Lets say, 99. 99 + 1 = 100, however you only have two digits, so 99 + 01 = 00. In that way 99 = -1. It could be printed either as 99 or -1.

There has to be defined a line, when a number is negative, and when it is positive. For example char 0x7f would be printed as 127. 0x80 (0x7f + 1) would be printed as -128.

In your case 60000 is greater than 0x7fff, so it's interpreted as a negative number.
Thanks for the reply hamsterman. I got one more question though

The range for this char type is -32768 to 32767.

Doing the math with the values from the above code

60000 - 32767 = 27233

-32768 + 27233 = -5535 (But the output on my program shows -5536)


Am I doing the math wrong? How come the ranges are not both the same (as in -32767 to 32767)??
I don't know where does the 1 go (My guess is that you should take 0 into account somewhere), but I do knot about the ranges.

Two bytes can represent 216 different values. Even number. Naturally you'd want half of them to be positive and another half - negative. But there is 0 which is neither, so you can't divide into equal parts.

I think there are more negative numbers, because that way the first (or maybe last? I don't know from which side to count..) bit of every negative number is 1.
216
Can be divided in signed and unsigned both of these have an equal amount of elements in them. Since -0 is commonly rewritten as 0, 0 is unsigned and therefor there is one positive digit 'less'.

Your calculation is based on the endpoints, not the lengths (which, as earlier stated, are equal). Your calculation is therefor wrong and should instead be:
60000 - 32768*2 = -5536
Which equals:
60000 - 216 = -5536
Last edited on
Hey thanks guys for clearing this up for me, I really appreciate it.
WARNING: overly technical explanation below

Note that this behavior is applicable to 2's compliment machines only. Granted this is virtually all platforms nowadays, but in case you come across a non 2's compliment machine the behavior will be different.

Numbers are stored as binary data. Each bit has a "weight" of 2n where 'n' is the bit index.

That is:

bit 0 = weight of 20 = 1
bit 1 = weight of 21 = 2
bit 2 = weight of 22 = 4

(Where bit 0 is the lowest bit)

The weight of the bits that are "on" (set) are effectively summed to produce the number. So if you have the following number in binary:

1
2
3
4
%00101100  <- number in binary
   ^ ^^
   | ||
 76543210  <- bit number (n)


as you can see bits 2, 3, and 5 are "on", so this number is:

22 + 23 + 25
= 4 + 8 + 32
= 44

Therefore 8 bit unsigned numbers effectively have a range of 0 (%00000000) to 255 (%11111111).

Signed numbers just make the weight of the highest bit negative. So for unsigned 8-bit numbers, the weight of the highest bit (bit 7) is 128. But for a signed 8-bit number, the weight is -128

For example:

1
2
3
4
%10000001

unsigned = 1 +  128 =  129
  signed = 1 + -128 = -127


Therefore signed 8 bit numbers effectively have a range of -128 (%10000000) to 127 (%01111111)

16-bit numbers are the same way, only the highest bit is bit 15 (weight of +/- 32768 depending on sign).


Now when you copy an unsigned variable (or a wider variable) to a signed var (or a var with fewer bits), the computer just stupidly copies over the bits, without giving thought to what the bits actually represent. So back to your original code:

1
2
3
4
short int i;
int j;
j = 60000;
i = j;


j is a 32-bit integer containing the number 60000. This means it contains the following bits:

j: 00000000000000001110101001100000

When you copy j to i on line 4, since i is a smaller type (only 16 bits), the computer drops the high 16 bits and only copies the low 16 bits:

1
2
j: 00000000000000001110101001100000
i:                 1110101001100000


And of course, since the high bit has a negative weight, this produces a strangely different negative number instead of the expected 60000.
Last edited on
Topic archived. No new replies allowed.