Safest Way to Convert Float to Integer in Python

Safest way to convert float to integer in python?

All integers that can be represented by floating point numbers have an exact representation. So you can safely use int on the result. Inexact representations occur only if you are trying to represent a rational number with a denominator that is not a power of two.

That this works is not trivial at all! It's a property of the IEEE floating point representation that int∘floor = ⌊⋅⌋ if the magnitude of the numbers in question is small enough, but different representations are possible where int(floor(2.3)) might be 1.

To quote from Wikipedia,

Any integer with absolute value less than or equal to 224 can be exactly represented in the single precision format, and any integer with absolute value less than or equal to 253 can be exactly represented in the double precision format.

Which is the efficient way to convert a float into an int in python?

Test it with timeit:

$ bin/python -mtimeit -n10000000 -s 'n = 1.345' 'int(n)'
10000000 loops, best of 3: 0.234 usec per loop
$ bin/python -mtimeit -n10000000 -s 'n = 1.345' 'n // 1'
10000000 loops, best of 3: 0.218 usec per loop

So floor division is only a faster by a small margin. Note that these values are very close, and I had to crank up the loop repeat count to iron out random influences on my machine. Even with such a high count, you need to repeat the experiments a few times to see how much the numbers still vary and what comes out faster most of the time.

This is logical, as int() requires a global lookup and a function call (so state is pushed and popped):

>>> import dis
>>> def use_int(n):
... return int(n)
...
>>> def use_floordiv(n):
... return n // 1
...
>>> dis.dis(use_int)
2 0 LOAD_GLOBAL 0 (int)
3 LOAD_FAST 0 (n)
6 CALL_FUNCTION 1
9 RETURN_VALUE
>>> dis.dis(use_floordiv)
2 0 LOAD_FAST 0 (n)
3 LOAD_CONST 1 (1)
6 BINARY_FLOOR_DIVIDE
7 RETURN_VALUE

It is the LOAD_GLOBAL and CALL_FUNCTION opcodes that are slower than the LOAD_CONST and BINARY_FLOOR_DIVIDE opcodes; LOAD_CONST is a simple array lookup, LOAD_GLOBAL needs to do a dictionary lookup instead.

Binding int() to a local name can make a small difference, giving it the edge again (as it has to do less work than // 1 floor division):

$ bin/python -mtimeit -n10000000 -s 'n = 1.345' 'int(n)'
10000000 loops, best of 3: 0.233 usec per loop
$ bin/python -mtimeit -n10000000 -s 'n = 1.345; int_=int' 'int_(n)'
10000000 loops, best of 3: 0.195 usec per loop
$ bin/python -mtimeit -n10000000 -s 'n = 1.345' 'n // 1'
10000000 loops, best of 3: 0.225 usec per loop

Again, you need to run this with 10 million loops to see the differences consistently.

That said, int(n) is a lot more explicit and unless you are doing this in a time-critical loop, int(n) wins it in readability over n // 1. The timing differences are too small to make the cognitive cost of having to work out what // 1 does here worthwhile.

Is it possible to convert the result from float to integer in Python?

Python's builtin function does the job:

>>> print(int(seconds_to_hours(int(3600)))
1
>>> print(type(int(seconds_to_hours(int(3600))))
<class 'int'>
>>>

Note that your code hours=seconds/int(3600) does not generate an integer, as opposed to C. If you want to do integer division, use double slash:

hours=seconds//int(3600)
# ^^

If you want to convert whatever into int without knowing whether it can, use this function:

def try_int(v)
try:
return int(v)
except ValueError:
return v

Then you'll be able to convert only those that are able to be converted into int into int.

Convert a float to an integer that fits within a range

The 0 to 1 range can be thought as a percentage so you just need to multiply that number by the range length and add it to the lower bound of the range.

Example:

The float is 0.7, so it represents a 70%.

The range is 1 to 9 then the range length is 9 - 1 = 8.

8 * 0.7 = 5.6

1 is the lower limit of the range so we add 1 to the 5.6 = 6.6

If you truncate the result you get a 6, and if you round it evenly you get a 7.

You can test this by testing the limits:

For 0 => the result is 1

For 1 => the result is 9

Convert floats to ints in Pandas?

To modify the float output do this:

df= pd.DataFrame(range(5), columns=['a'])
df.a = df.a.astype(float)
df

Out[33]:

a
0 0.0000000
1 1.0000000
2 2.0000000
3 3.0000000
4 4.0000000

pd.options.display.float_format = '{:,.0f}'.format
df

Out[35]:

a
0 0
1 1
2 2
3 3
4 4

How do I parse a string to a float or int?

>>> a = "545.2222"
>>> float(a)
545.22220000000004
>>> int(float(a))
545

Python float to Decimal conversion

Python <2.7

"%.15g" % f

Or in Python 3.0:

format(f, ".15g")

Python 2.7+, 3.2+

Just pass the float to Decimal constructor directly, like this:

from decimal import Decimal
Decimal(f)


Related Topics



Leave a reply



Submit