Because… dynamic range sucks.
Your display is probably close to sRGB and using 8 bits integer encoding. So the highest value that will get rounded to 0 when converting to
uint8 sRGB is (0.5 / 255) / 12.92 = 0.0001518 where 12.92 is the encoding transfer function of sRGB near black. If we compute the \log_2 of this value, we get -12.69 EV.
So, that means that sRGB can encode 12.69 EV of lightness data between “pitch black” and “full white” (regardless of whether the screen can actually display all of them later or not – this is pure data encoding).
Meanwhile, middle grey \approx 0.1845, which in \log_2 is -2.44 EV. To sum up:
- display white is at 0 EV (it’s our reference),
- middle grey is at - 2.44 EV,
- display black is at - 12.69 EV (and everything darker will get rounded the same -12.69 EV, encoded 0 in this space).
You see that our typical dynamic range is clearly unbalanced in favour of shadows.