Why doesn't C have unsigned floats?
Solution 1:
Why C++ doesn't have support for unsigned floats is because there is no equivalent machine code operations for the CPU to execute. So it would be very inefficient to support it.
If C++ did support it, then you would be sometimes using an unsigned float and not realizing that your performance has just been killed. If C++ supported it then every floating point operation would need to be checked to see if it is signed or not. And for programs that do millions of floating point operations, this is not acceptable.
So the question would be why don't hardware implementers support it. And I think the answer to that is that there was no unsigned float standard defined originally. Since languages like to be backwards compatible, even if it were added languages couldn't make use of it. To see the floating point spec you should look at the IEEE standard 754 Floating-Point.
You can get around not having an unsigned floating point type though by creating a unsigned float class that encapsulates a float or double and throws warnings if you try to pass in a negative number. This is less efficient, but probably if you aren't using them intensely you won't care about that slight performance loss.
I definitely see the usefulness of having an unsigned float. But C/C++ tends to chose efficiency that works best for everyone over safety.
Solution 2:
There is a significant difference between signed and unsigned integers in C/C++:
value >> shift
signed values leave the top bit unchanged (sign extend), unsigned values clear the top bit.
The reason there is no unsigned float is that you quickly run into all sorts of problems if there are no negative values. Consider this:
float a = 2.0f, b = 10.0f, c;
c = a - b;
What value does c have? -8. But what would that mean in a system without negative numbers. FLOAT_MAX - 8 perhaps? Actually, that doesn't work as FLOAT_MAX - 8 is FLOAT_MAX due to precision effects so things are even more screwy. What if it was part of a more complex expression:
float a = 2.0f, b = 10.0f, c = 20.0f, d = 3.14159f, e;
e = (a - b) / d + c;
This isn't a problem for integers due to the nature of the 2's complement system.
Also consider standard mathematical functions: sin, cos and tan would only work for half their input values, you couldn't find the log of values < 1, you couldn't solve quadratic equations: x = (-b +/- root (b.b - 4.a.c)) / 2.a, and so on. In fact, it probably wouldn't work for any complex function as these tend to be implemented as polynomial approximations which would use negative values somewhere.
So, unsigned floats are pretty useless.
But that doesn't mean to say that a class that range checks float values isn't useful, you may want to clamp values to a given range, for example RGB calculations.