Hacker News new | ask | show | jobs
by kr0bat 937 days ago

  To find the two’s complement of 5, we invert all the bits (changing 0s to 1s and 1s to 0s) and then add one to the result.
I am embarrassed by the fact that I wasn't aware of this. I always interpreted the two's complement as the difference between the all the numbers before the high bit, minus the high bit. Aka 10000000 – 01111011 = 0101
4 comments

When I first learned two's complement I sort of accepted it as something to memorise for a test and didn't really understand (or care) why it worked.

What really made it click for me was thinking of it as modular arithmetic. If you consider 8-bit integers, they range from 0-255 and you're actually working modulo 256. So you can think of 0-127 as your non-negative numbers. The numbers from 128-255 behave as negatives modulo 256 (e.g. -1 mod 256 = 255).

Good point; I wish I'd added that.
That it's the same thing may be more familiar in base 10: for example with 3-digit numbers, the 10's complement of (say) 428 is 1000-428 = 572, and you get the same result if you "invert" each digit (subtract from 9) and add 1: 571 + 1 = 572. This is just because (999-x)+1 = 1000-x.
One of the advantages of two's compliment (particularly relevant in early hardware that really needed to minimize gate count) is that you can use an adder to perform subtraction: just flip all of the bits of the argument to subtract, and have an extra carry input to pretend you have a carry-in bit to be added to the least significant bit.

If you want your CPU to efficiently support multi-precision addition, you can have an overflow machine state flag and have an instruction that uses that overflow flag as the carry-in to the least significant bit during addition.

I find it much easier to think of everything in unsigned terms. If I want 8bit -5, I really want 256-5=251. I've done plenty of that in my time but I don't think I've once consciously inverted bits and added 1.