This is all about modeling :
When you want to design a computer, you need to adopt conventions to how you represent data, and how you compute them. And of course, provide different models with different operations and properties (performance, memory space required, hardware implementation complexity etc.)
Turns out, with computation based on electricity (thus electronics), the most convenient way we found to represent an information is to use the voltage level. ...And the most convenient way to compute with these voltage level is considering two states : Presence of a voltage and absence of voltage.
Here comes the "bit".
This is why we use binary to represent numbers : a succession of electronic pins with either a high voltage (1) or a low voltage (0).
However, if you count using binary, you can only represent natural numbers (0, 1, 2, ...). Exactly 2^n (where n is the number of bits you have) numbers.
This permits you to do addition multiplication, division, and subtraction if you ensure the first operand is greater than the second, end if you check the result would not exceed the number of bits you have.
Then, some smart guys came and though : "What happens when you do n - m with m > n, using exactly the same algorithm ?"
...And what happens is that it actually kinda work : you just have to add one to your number if you have a carry (wrap around) after, and consider that both 0...0 and 1...1 represents 0. That's One's complement Ones'_complement
However, by doing so, you have to reserve one bit for the sign. Technically, you can represent values from -(2^(n-1)-1) ≤ n ≤ 2^(n-1)-1
Which are : (2^n)-1 (two representations for 0). In this representation, you just have to swap all the bits to negate a number.
Then even smarter guys came and tell "What if we consider there is always a wrap around when we negate the number ?" ...That means you add one after you have swapped the bits. And you get 2's complement Two's complement
Using it, your zero has only One representation, and you can again represent 2^n numbers ( with 2^(n-1) ≤ n ≤ 2^(n-1)-1 ). Plus, the computation of a-b
really just is a+(-b)
, which only requires two kind of operation : add(a, add(swap(b), 1)))
Another nice thing about 2's complement, is that the addition algorithm is the same as the unsigned one. Therefore you get the same properties, and use the same hardware to do both. This is why it's the representation used in most computers.
In short, signed and unsigned can represent the same count of numbers, but on a different range, and now, you know which precisely and why. For more detail about the algebraic structure obtained, read this response : https://mcmap.net/q/20713/-signed-versus-unsigned-integers
Then use one or the other depending on the context (note however that for some operation, like <
, the treatment is different when casting : ((signed) -1) < 5
but ((unsigned) -1) > 5