Online Tools » Computers » unsigned ⇔ signed |
en sv |

Whole numbers are stored in computers as a series of bits (ones and zeroes) of fixed length. The most common sizes are 8, 16, 32 and 64 bits. The bits can be interpreted in two different ways. They can either be interpreted as an *unsigned* value which means that no negative values are allowed, or they can be interpreted as a *signed* value which allows both positive and negative values. The maximum value that can be stored is about twice as big with unsigned compared to with signed.

Since computer memory consist of nothing but ones and zeroes the most natural way to interpret data is to use the binary numeral system. This means that for an n-bit number there are 2^^{n} possible values, but since the counting starts from zero the highest possible value is only 2^^{n} - 1.

The value contributed by an individual bit with the value one in a binary number is 2^^{b} where *b* is the bit position, counted from right to left, starting from zero. The total value of a binary number can thus be calculated by adding all these values for all the bits.

The binary number 1011 can be calculated as follows:

1 | 0 | 1 | 1 | |||||

1×2^^{3} |
+ | 0×2^^{2} |
+ | 1×2^^{1} |
+ | 1×2^^{0} |
= | |

8 | + | 0 | + | 2 | + | 1 | = | 11 |

The lack of sign (+/−) makes it impossible to represent negative values.

To be able to represent negative values the most significant bit (the one furthest to the left) is often used to signify that the value is negative. It's therefore very important to know how many bits are being used and to always write out all bits so that it is clear what value the sign bit has.

Signed positive values (including zero) can be stored the same way as unsigned values but since one bit is reserved for the sign the highest possible value for an n-bit number becomes 2^^{n-1} - 1.

A naive way to handle the negative values is to note if the sign bit is 1, which means that the value is negative, and then interpret the rest of the bits as before.

1 | 0 | 1 | 1 | ||||||

− | ( | 0×2^^{2} |
+ | 1×2^^{1} |
+ | 1×2^^{0} |
) | = | |

− | ( | 0 | + | 2 | + | 1 | ) | = | −3 |

The disadvantage with this approach is that there are now two possible bit patterns that code for the value zero (±0), and it also complicates the calculations that the computer has to do. To demonstrate the problem the following example will add two negative values using the normal rules for binary numbers.

1011 | ( −3 ) | ||

+ | 1010 | ( −2 ) | |

0101 | ( +5 ) | ✗Incorrect |

The actual sum is 10101 but since we are limited to 4 bits the extra digit is simply lost. The result is correct except for the sign that is incorrect. To handle this we could add a new rule that says that the sign bit should be 1 if both values are negative, but we will see that it becomes more complicated when the two numbers have different sign.

1011 | ( −3 ) | ||

+ | 0010 | ( +2 ) | |

1101 | ( −5 ) | ✗Incorrect |

Here the result is completely wrong. It is of course possible to add even more special rules for how the different situations should be handled but it would lead to unnecessary complexity and more expensive hardware. This way of handling negative values can be used in some situations (e.g. in floating-point numbers) but for whole numbers there is something called *two's complement* that is almost always used because it solves the problems mentioned here in a relatively easy way.

The smallest possible value for an n-bit number with two's complement is -2^^{n-1}. The bit pattern for this value is a one (sign bit = 1) followed by n-1 zeroes. For a 4-bit number this means that the smallest value is -8 and is stored as 1000.

The rest of the negative values are ordered such that the nearest higher value can always be found by doing normal binary addition with 1. For a 4-bit number 1001 codes for -7, 1010 codes for -6, and so on, all the way up to 1111 which codes for -1.

If we continue by adding 1 to 1111 it gives us 10000, but since we only use 4 bits the 1 goes away and we get 0000 which codes for 0. The rest of the positive values follows the same way. Note how we were able to go all the way from the smallest to the largest value without having to treat negative values any different.

This way of representing numbers allows addition, subtraction and multiplication to be carried out by the computer in the same way regardless of whether the numbers are signed or unsigned. If the incorrect calculations above are repeated with two's complement we'll see that it will now give us the correct results.

1101 | ( −3 ) | ||

+ | 1110 | ( −2 ) | |

1011 | ( −5 ) | ✓Correct |

1101 | ( −3 ) | ||

+ | 0010 | ( +2 ) | |

1111 | ( −1 ) | ✓Correct |

Note that the only difference from earlier is which bit patterns that code for which numbers. The way in which the numbers are added has not changed.

To get the two's complement representation of a negative number it can first be written as a positive number, then the bits are inverted, and finally an addition with 1 is carried out.

To demonstrate how -3 can be written with two's complement in 4 bits we first note that 3 is written in binary as 0011. Inverting the bits results in 1100. The last step is to add 1 which gives us 1101. This means that 1101 is the two's complement representation of -3.

The opposite calculation, i.e. going from two's complement to finding the negative value that is represented, can be done by repeating the exact same steps. If 1101 is first inverted and then 1 is added we get 0011 which codes for 3. We can thus conclude that 1101 codes for -3.