问题
If I have something like this:
int i = 123;
float f = 123.1;
if (f > i) {} else {}
The i
will be promoted to a float
and the comparison will become if (float > float)
. My question is why does the int
variable needs to be promoted to a float
in the first place, Is it because its easier for the computer to compare two plain numbers than trying to figure out what the bits of each number represent and then compare that?
回答1:
Because "There are no numbers". Computers don't compare numbers, and don't work with numbers. They work with, and compare, bit patterns.
The fact bit patterns represent numbers is due to the "encoding" we use to represent numbers as bit patterns. And once we choose an encoding, operations on numbers become operations on bit patterns. And once we choose another encoding, same operations on numbers become other operations on bit patterns.
Now, if you have 10 possible way to represent numbers, you should support 100 possible ways to do binary operations (or even 1000, if you also want to consider the result!).
Since this cannot scale, you have to reduce. And the simpler way to reduce is to eliminate similar things by splitting them into parts: first convert all all numbers to go into a common encoding, then operate on that encoding and eventually convert the result back to the desired one.
This is essentially due to the fact that operation on numbers having a same encoding can be implemented easily since same rules apply everywhere, and this can be done by reusing the same circuitry.
But for this to work, the "common format" must be chosen so that both the operands can be represented. And representing an int into a float has more chances to succeed than representing a float into an int.
回答2:
The rules were written as they were because it was easier for compilers to define a small number of ways of performing operations, along with a means of normalizing operands, than to define a larger number of ways. Even just considering the six types int, unsigned int, long, unsigned long, float, double, evaluating an expression like x < y
without converting operands would require special-case code to handle the following cases:
- int/unsigned int (in either order)
- long/unsigned long
- int/float
- long/float
- long/double
In the 1970s, having to handle sixteen different combinations of operand types for x > y
instead of six would have been excessively expensive, especially given that the compiler would have to generate more complicated code to perform such comparisons "accurately" than would be required if everything were coerced to the same type.
Personally, I think that modern language designers should free themselves from the 1970s mindset, but it seems to have become pretty well established (though it may also be worth noting that if the nasty variable-argument-passing behavior of "long double" hadn't made the type useless, that type would on many platforms have been able to represent the value of every long
or unsigned long
value, so promoting fixed float/integer arguments to that type would have yielded semantically-correct results very easily).
来源:https://stackoverflow.com/questions/28007936/why-the-operands-of-an-operator-needs-to-be-of-the-same-type