LeopardShark
LeopardShark

Reputation: 4446

Which stage to round at?

In Python, at what stage should round be used? Take this example: 10 * math.log(x) + 10 If I want this to be rounded which should I use?

round(10 * math.log(x) + 5)
round(10 * math.log(x)) + 5
10 * round(math.log(x)) + 5

My guess would be that rounding early would run the fastest because more arithmetic happens with integers, which seem like they should be faster than floats. Rounding seems less likely to break if some later values change.

Would the answer be the same with int()?

Upvotes: 1

Views: 129

Answers (5)

jpp
jpp

Reputation: 164773

Don't prematurely optimize. In many cases, it's not highly optimized mathematical functions which slow down programs, but the logic, structure or data types used in the calculation.

To that end, I recommend you use cProfile to identify bottlenecks. Note that cProfile itself has an overhead, so it is mostly useful for relative comparisons.

As per @glibdud's comment, you have to understand how rounding will affect your calculation. Try a few examples, or perform a test to see how your error may vary across a large number of inputs.

Upvotes: 2

Emmanuel Ferran
Emmanuel Ferran

Reputation: 726

Please note that the Python Math.log() function is the base of e by default. By your questions it's unclear what base you expect so I'll assume log base of 10 like Google does. In order to make it equivalent to the mathematical function provided the code would need to be:

import math
#assuming x equals 2
x = 2
function1 = round(10 * math.log(x,10) + 5)
function2 = round(10 * math.log(x,10)) + 5)
function3 = 10 * round(math.log(x,10)) + 5)
function4 = 10*math.log(x,10)+5

print(function1)
print(function2)
print(function3)
print(function4)

Now, assuming x = 2, the calculations for the mathematical equation is 8.01029995664 Looking at the printed output from the above code:

8
8
5
8.010299956639813

It clearly shows that functions 1,2 and 4 are roughly mathematically equivalent with function 3 being incorrect. This is because the round function uses Half and Above rule to round up. Math.log(2,10) results in 0.3, so when the round function happens it drops to zero.

As for the equivalence of int() and round() the link referenced by IMCoins is pretty good. The summation is that int() removes decimal values from a number and the round uses the half and above rule so it will act like the int() for anything less than x.5.

As for the speed question, if accuracy is non-negotiable it would be best to round upon completion of the answer due to the same reasons as why function 3 was wrong above. If you're fairly certain you can round safely at a step, then I agree with the answer above to use CProfile and find the bottlenecks

Hope this helps.

Upvotes: 1

Joe
Joe

Reputation: 7131

I have no clue, but let's see :)

import time
import math

n = 1000000
x = 5

def timeit(f):

    t_0 = time.perf_counter()

    for _ in range(n):
        f()

    t_1 = time.perf_counter()

    print((t_1 - t_0)/ n)        

def fun1():
    round(10 * math.log(x) + 5)

def fun2():
    round(10 * math.log(x)) + 5

def fun3():
    10 * round(math.log(x)) + 5    

[timeit(_) for _ in [fun1, fun2, fun3]] 

On my computer the last one is slightly faster than the others.

Upvotes: 0

Preston Martin
Preston Martin

Reputation: 2963

That entirely depends upon how you want your answer to be formatted and interpreted. I would not be hung up on the speed of the round function though (unless the very minor performance gain is crucial to your program). I would think about what I'm trying to accomplish by rounding. If your goal is to produce an output that is rounded to the nearest integer (for simplicity) then I would encompass your entire arithmetic statement into the round function. If your goal is to only use rounded integers in your log calculations (maybe because you don't want to use floats) then you should only round the math.log(x) function. There is no technical reason why you would use either, but there is definitely a logical reason that you would want to choose either of your options.

Upvotes: 1

IMCoins
IMCoins

Reputation: 3306

The earlier you are rounding, the more your result will be affected by this rounding. In my opinion, it all depends on the expectations of your program.

As for the difference between int() and round(), this thread answers it perfectly.

To be more specific to your question about performance : The round() function, that is a python built-in, is implemented in C, and you shouldn't really worry about performance as it will be very, very negligible.

Round function

Upvotes: 1

Related Questions