Why does Python return True
when I compare int
and float
objects which have the same value?
For example:
>&
Objects of different types, except different numeric types, never compare equal.
And:
Python fully supports mixed arithmetic: when a binary arithmetic operator has operands of different numeric types, the operand with the “narrower” type is widened to that of the other, where integer is narrower than floating point, which is narrower than complex. Comparisons between numbers of mixed type use the same rule.
https://docs.python.org/3/library/stdtypes.html#numeric-types-int-float-complex
The comparison logic is implemented by each type's __eq__ method. And the standard numeric types are implemented in a way that they support comparisons (and arithmetic operations) among each other. Python as a language never does implicit type conversion (like Javascript's ==
operator would do implicit type juggling).
From the documentation:
Python fully supports mixed arithmetic: when a binary arithmetic operator has operands of different numeric types, the operand with the “narrower” type is widened to that of the other, where plain integer is narrower than long integer is narrower than floating point is narrower than complex. Comparisons between numbers of mixed type use the same rule.
According to this 5*2 is widened to 10.0 and which is equal to 10.0 If you are comparing the mixed data types then the result will be considered on the basics of data type which is having long range, so in your case float range is more then int float max number can be --> 1.7976931348623157e+308 int max number can be --> 9223372036854775807
Thanks
It's not as simple as a type conversion.
10 == 10.0
delegates to the arguments' __eq__
methods, trying (10).__eq__(10.0)
first, and then (10.0).__eq__(10)
if the first call returns NotImplemented
. It makes no attempt to convert types. (Technically, the method lookup uses a special routine that bypasses instance __dict__
entries and __getattribute__
/__getattr__
overrides, so it's not quite equivalent to calling the methods yourself.)
int.__eq__
has no idea how to handle a float:
>>> (10).__eq__(10.0)
NotImplemented
but float.__eq__
knows how to handle ints:
>>> (10.0).__eq__(10)
True
float.__eq__
isn't just performing a cast internally, either. It has over 100 lines of code to handle float/int comparison without the rounding error an unchecked cast could introduce. (Some of that could be simplified if the C-level comparison routine didn't also have to handle >
, >=
, <
, and <=
.)
You can have a look at the source code for the CPython implementation.
The function is preceded by this comment explaining how the conversion is attempted:
/* Comparison is pretty much a nightmare. When comparing float to float, * we do it as straightforwardly (and long-windedly) as conceivable, so * that, e.g., Python x == y delivers the same result as the platform * C x == y when x and/or y is a NaN. * When mixing float with an integer type, there's no good *uniform* approach. * Converting the double to an integer obviously doesn't work, since we * may lose info from fractional bits. Converting the integer to a double * also has two failure modes: (1) an int may trigger overflow (too * large to fit in the dynamic range of a C double); (2) even a C long may have * more bits than fit in a C double (e.g., on a 64-bit box long may have * 63 bits of precision, but a C double probably has only 53), and then * we can falsely claim equality when low-order integer bits are lost by * coercion to double. So this part is painful too. */
Other implementations are not guaranteed to follow the same logic.
The simple answer is that the langue is designed this way. Here is an excerpt from the documentation supporting this:
6.10.1 Value Comparisons
Numbers of built-in numeric types (Numeric Types — int, float, complex) and of the standard library types fractions.Fraction and decimal.Decimal can be compared within and across their types, with the restriction that complex numbers do not support order comparison.
In other words, we want different numeric types with the same value to be equal.
PEP 20
Special cases aren't special enough to break the rules.
Although practicality beats purity.
What benefit is there to making numeric types not comparable, besides making life difficult in most common cases?
==
is a comparison operator
You are actually asking the interpreter if both sides of your expression are equal or not.
In other words you are asking for it to return a Boolean value, not to convert data types. If you want to convert the data types you will have to do so implicitly in your code.