I've been using n = int(n) to convert a float into an int.
Recently, I came across another way to do the same thing :
n = n // 1
Which is the most efficient way, and why?
I've been using n = int(n) to convert a float into an int.
Recently, I came across another way to do the same thing :
n = n // 1
Which is the most efficient way, and why?
Using float.__trunc__() is 30% faster than builtins.int()
@MartijnPieters trick to bind builtins.int is interesting indeed and it reminds me to An Optimization Anecdote. However, calling builtins.int is not the most efficient.
Let's take a look at this:
python -m timeit -n10000000 -s "n = 1.345" "int(n)"
10000000 loops, best of 5: 48.5 nsec per loop
python -m timeit -n10000000 -s "n = 1.345" "n.__trunc__()"
10000000 loops, best of 5: 33.1 nsec per loop
That's a 30% gain! What's happening here?
It turns out all builtints.int does is invoke the following method-chains:
1.345.__int__ is defined return 1.345.__int__() else:1.345.__index__ is defined return 1.345.__index__() else:1.345.__trunc__ is defined return 1.345.__trunc__()1.345.__int__ is not defined 1 - and neither is 1.345.__index__. Therefore, directly calling 1.345.__trunc__() allow us to skip all the unnecessary method calls - which is relatively expensive.
What about the binding trick? Well float.__trunc__ is essentially just an instance method and we can pass 1.345 as the self argument.
python -m timeit -n10000000 -s "n = 1.345; f=int" "f(n)"
10000000 loops, best of 5: 43 nsec per loop
python -m timeit -n10000000 -s "n = 1.345; f=float.__trunc__" "f(n)"
10000000 loops, best of 5: 27.4 nsec per loop
Both methods improved as expected 2 and they maintain roughly the same ratio!
1 I'm not entirely certain about this - correct me if somebody knows otherwise.
2 This surprised me because I was under the impression that float.__trunc__ is binded to 1.345 during instance creation. It'd be great if anyone'd be kind enough to explain this to me.
There is also this method builtins.float.__floor__ that is not mentioned in the documentation - and is faster than builtins.int but slower than buitlins.float.__trunc__.
python -m timeit -n10000000 -s "n = 1.345; f=float.__floor__" "f(n)"
10000000 loops, best of 5: 32.4 nsec per loop
It seems to produce the same results on both negative and positive floats. Would be awesome if someone could explain how this fits among the other methods.