I am doing the following:
TOLERANCE = 13
some_float = ...
round(some_float, TOLERANCE)
This is run many times, so performance is important. I have to round some_float due to floating point representation error. I don't actually need to "round" the number in that sense, just remove digits after 13 trailing digits.
Is there a faster way to do this?
I've made some benches to compare round(some_float, TOLERANCE)
with int(some_float * p + 0.5)/p
(with p as 10**TOLERANCE)
and here are the results:
- round: 6.20 seconds
- int divide+multiply: 3.53
my bench:
import timeTOLERANCE = 5
some_float = 12.2439924563634564564564
nb_loops = 10000000start_time = time.time()
for _ in range(nb_loops):r1 = round(some_float, TOLERANCE)
print(r1,time.time()-start_time)start_time = time.time()
p = float(10**TOLERANCE)
for _ in range(nb_loops):r2 = int(some_float * p + 0.5)/p
print(r2,time.time()-start_time)
result:
12.24399 6.208600997924805
12.24399 3.525486946105957
so the int
solution is faster. round
is probably better at handling the rounding of negative numbers (as someone commented, it makes a lot extra calls, so the code is more complex). The rounding may be different depending on the sign of the input number. Accuracy vs raw speed, again.
Add 0.5
or not to round or truncate. This seems to be a detail for you, but the int
solution (provided that 10**TOLERANCE
is precomputed) seems faster.
If you want to use that technique, you could be tempted to put the rounding code in a function:
TOLERANCE = 5
p = float(10**TOLERANCE)
def my_round_5(some_float):return int(some_float * p + 0.5)/p
and call it like this:
r2 = my_round(some_float)
that would be still faster than round
, but a tad slower than using the formula inline (because function call isn't free)
note that I've used p = float(10**TOLERANCE)
and not p = 10**TOLERANCE
so the code is compatible with python 2 (else it would truncate the decimal part due to integer division)