Why is hexadecimal more machine-friendly than decimal?
language-agnostic
Solution
As you have noticed. Both are equally machine friendly. Both `10` and `0x0a` is the same number. In the same way that 1/2 and 0.5 is the same number in decimal.
From the machine's point of view it doesn't matter. The machine doesn't see "10" or "0x0a". The machine just sees `00001010`. Actually, not even that. What's really in the machine are two bits at a voltage (or charge) level that represents `on` and eight bits at a voltage level that represents `off`.
The reason for the popularity of hexadecimal numbers is that it is easier to read for a "human". At least for engineers and programmers (to be honest I'm a bit hesitant to mention programmers because it isn't true for a vast majority of programmers).
First of all, engineers and programmers who have to write device drivers rarely care if a variable has the value 10 or 62 or 233 or whatever. They do care if a number fits within memory or not. What values are sent to the hardware is the user's problem. Weather or not that value can be sent is what the engineer or driver writers have to deal with.
For this hex numbers have a very significant advantage because each character is aligned to exactly one nybble. Which means that a byte is represented by exactly two characters and two characters represent exactly one byte. Contrast this with decimals where a byte requires three characters but three characters can represent up to 12 bits.
Quick, can you fit 133 in one byte? Maybe you know that one byte can represent numbers from 0-255 so it may seem obvious, but a number like 0x133 obviously requires two bytes. In fact, to make it more clear you'll often see engineers write `(hex) 01 33` in data dumps or documentation to make it more obvious that it's two bytes.
It's even more useful at higher bit counts. Quick, can you fit 4311111111 in 32 bits? I have a vague idea that 32 bits is roughly 4 million but am not sure if that number fits in 32 bits. Contrast this with it's hexadecimal representation: `0x1 00F6 55C7` it is much more obvious that you need at least 33 bits to represent that number.
Engineers are also used to seeing bit patterns in hexadecimal. The basic pattern is simple:
1 = first bit
2 = second bit
4 = third bit
8 = fourth bit
So, if you want to set bit number 19 in a register, your thought process would go something like this:
Bit 19 is after the 16th bit. And you know that the 16th bit is `0x0000 8000`
(when I think in hex, my mind always add the blank spaces for clarity).
19 is 3 bits higher than 16. And the number that represents the third bit is 4.
So bit number 19 is: `0x0004 0000`
That part I mentioned about the 16th bit is another basic pattern most engineers trained to read hex recognize:
00 00 00 80 = bit no 8
00 00 80 00 = bit no 16
00 80 00 00 = bit no 24
80 00 00 00 = bit no 32
Another common pattern that I've trained myself to recognize is square waves:
_ _ _ _
0x55 = _| |_| |_| |_| (01010101)
_ _ _ _
0xaa = |_| |_| |_| |_ (10101010)
_ _ _ _
0x33 = _ _| |_ _| (00110011)
_ _ _ _
0xcc = |_ _| |_ _ (11001100)
_ _ _ _
0x66 = _| |_ _| |_ (01100110)
_ _ _ _
0x99 = |_ _| |_ _| (10011001)
_ _ _ _
0xf0 = |_ _ _ _ (11110000)
_ _ _ _
0x0f = _ _ _ _| (00001111)
Which means, that for someone like me, if you tell me you want to set the first, third and fourth bits of a variable in under 2 seconds I'd go Aha: 0x0d. Because obviously third and foutth bits is `c` (square wave pattern) so add bit one and it becomes `d`.
You may be thinking to yourself: wait a minute, wouldn't binary representation be better. Well, yes `(bin) 0000 1101` is much more obviously the first, third and fourth bits set. The problem with binary representation is that at anything higher than 8 bits the number becomes too large for the human eye to easily comprehend and in practice have lead to even more mistakes and misunderstandings compared to hexadecimal.
Also, not many languages have support for binary representation and of those that do most don't allow spaces or other separators (underscore for example) between digits which makes the number even less readable compared to hex.
Hexadecimal hasn't always been the preferred representation among engineers and (some) programmers. At one point octal numbers were just as popular. But octals have the same problem as decimal. A byte requires three octal digits to represent but three octal digits can actually represent 9 bits. So it doesn't have that nice perfect division that hexadecimal has.
There is at least one other method to represent binary values that's very popular. You've seen it many times but may not have realized what it actually is: the dotted decimal notation of IPv4 addresses is actually an encoding that represents the values as decimal yet attempts to fit them within the structure of memory:
192.168.0.1 = 11000000 10101000 00000000 00000001
(192) (168) (0) (1)
Alas, as we move forward with IPv6, we seem to have decided to go back to hexadecimal encoding.
Problem
This may be a silly question since I can see a relationship between "16 is a power of two" and "each bit represents 2^(n of bits) values", so it is logical that two hex numerical digits represent a byte's possible values. However I am still too blind to see how it would be any better than decimal as either way it needs to be converted into binary. Can someone explain the numerical notation conversion process in low-level pseudo-programming to make it more understandable? I really don't see how the conversion process is shortened if there is a conversion going on anyway.