Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implicit conversion while comparing numeric values in Python

Tags:

python

While working on an issue, I stumbled at something I cannot really undestand on my own.

I have a variable: a = pow(2, 1024)

Its type is long int. If I try casting it explicitly to float, like float(a), I receive OverflowError. The number is too big to fit in 64bit float, so it's understandable.

Then I try implicit cast, through mutliplying it by a float number:

b = a * 11.0

Once again, the OverflowError occurs, which is fine, because according to python docs, implicit conversion from long int to float happens. So the result is like before.

Finally, I try comparison:

a > 11.0 returns True. The OverflowError doesn't occur. And that confuses me a lot. How does the Python comparison mechanism work, if it doesn't require numerics to be in the same format? Accordind to this,

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. The constructors int(), long(), float(), and complex() can be used to produce numbers of a specific type.

My question is, why a is not being cast to float in forementioned comparison?

The version of Python I'm using is 2.7.15. Thanks in an advance

like image 509
Michał Górnicki Avatar asked Jun 05 '18 11:06

Michał Górnicki


People also ask

What is implicit type conversion in Python?

In Implicit type conversion, Python automatically converts one data type to another data type. This process doesn't need any user involvement. Let's see an example where Python promotes the conversion of the lower data type (integer) to the higher data type (float) to avoid data loss.

What is implicit type conversion give an example?

Implicit data type conversion is done automatically by the python compiler without any involvement of the user. The compiler converts smaller data types into larger data types to prevent any loss of data, for example, conversion of int to float.

Can you compare ints and floats in Python?

You shouldn't, in general, compare floats for equality without some care, but comparing floats for relativity (> or <) is perfectly fine. Your update is due to precision errors - they are a fact of computing, and shouldn't matter to you in 99.9% of cases as they difference is too small to care about.

Which conversion can be performed implicitly?

We cannot perform implicit type casting on the data types which are not compatible with each other such as: Converting float to an int will truncate the fraction part hence losing the meaning of the value. Converting double to float will round up the digits.


Video Answer


2 Answers

From the source:

/* 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) a long 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.
 */

As such, the potential pitfalls of conversion are taken into account.

like image 73
Phylogenesis Avatar answered Oct 10 '22 16:10

Phylogenesis


The exact error is OverflowError: int too large to convert to float

Which also means that any int that generates that error is by definition bigger then any possible float. So just checking if it's bigger should return True.

I'm not entirely sure, but I wouldn't be surprised if the implementation is just catching this error in the background (when trying to cast to float) and returning True in that case.

That is always true with the exception of float('inf') which is a special case that should return False (and does)

like image 32
Ofer Sadan Avatar answered Oct 10 '22 17:10

Ofer Sadan