Basic

Negative numbers in bits

A fixed number of bits can hold negative numbers too. The machine uses twos complement, where the top bit marks a negative value, so the same bits read as a negative number.

What you will see

-128 127

About 2 min of reading

Try It

Work with signed bits.

1

Print negative one in binary.

print(bin(-1))

Before you run it, say out loud what it will print. Then open the answer.

What it prints
-0b1
Python prints a sign and magnitude, the stored form is all ones.
2

Negate five by flipping and adding one.

print(~5 + 1)

Before you run it, say out loud what it will print. Then open the answer.

What it prints
-6
3

Read one byte signed and unsigned.

print(int.from_bytes(b"\xff", "signed")) print(int.from_bytes(b"\xff", "unsigned"))

Before you run it, say out loud what it will print. Then open the answer.

What it prints
-1 255
4

Show the range of eight bits.

print(-128, 127)

Before you run it, say out loud what it will print. Then open the answer.

What it prints
-128 127

Data Flow

Twos complement stores negatives in the same bits, with the top bit marking sign and one extra negative value.
1 top bit marks negative
↓
2 flip then add one negates
↓
3 eight bits hold -128 to 127
↓
4 signed and unsigned are two readings
Line by line

Read the first example one line at a time. A line that prints shows what appears on screen; the rest set things up quietly.

print(bin(-1)) -0b1
Why this works
Twos complement is the standard

Every modern machine stores signed integers this way. The rule is not a language detail, it is how hardware works.

Signed and unsigned are readings

The bytes are the same. Asking for a signed reading treats the top bit as a sign, and that choice changes the number.

Examples

The top bit

print(-1)
print(bin(-1))

Negative one is all ones. The top bit being 1 marks a negative value in twos complement.

Flip and add one

print(~5 + 1)

Flipping the bits of five and adding one gives its negative. That is the rule for negating a fixed row.

Negatives add for free

print(-3 + 3)

A number plus its negative is zero with no special case. That is the reason twos complement was chosen.

The range is lopsided

print(-128, 127)

Eight bits hold -128 to 127. There is one more negative than positive, because zero takes a slot.

Reading a signed byte

print(int.from_bytes(b"\xff", "signed"))
print(int.from_bytes(b"\xff", "unsigned"))

The same byte is -1 signed and 255 unsigned. The signed flag decides how the top bit is read.

Zero is not two things

print(0 == -0)

There is one zero. A system with two zeros would waste a value, which is one reason this rule won.

Subtraction is addition

print(7 + (-3))

Subtracting is adding a negative. The machine only needs one adder, which is another gift of this rule.

The sign is a bit

print((-1).bit_length())

The sign is not a separate flag, it is the top bit of the row. Reading it wrong turns a large positive into a negative.

Words this lesson uses

Each one is defined here on this site. Open the entry for the full definition and the other words it points at.

← Text stored as numbers
Previous Lesson
Text stored as numbers
Next Lesson
The limit of a fixed width
The limit of a fixed width →