3

I want to define a function, e.g. a polynomial, from a list of prefactors. Something like

order = [1,0,1] def poly(x): res = 0 for i, o in enumerate(order): res += o * x**i return res 

so poly(x) returns 1 + x².

I need to call that function multiple times for different x, but with the same prefactors. The above function executes the for loop every time it is called, which is rather inefficient, especially if the order list is long. How can I loop only once and call the result for different x? What is the pythonic solution?

8
  • 2
    You have the most efficient solution that I can think of at this time Commented Aug 11, 2017 at 15:50
  • I would avoid raising to the power at each iteration by keeping the previous value and just multiplying it by x each iteration. This will also eliminate the need in enumerate and i. Commented Aug 11, 2017 at 15:54
  • See if stackoverflow.com/questions/533382/… helps. Commented Aug 11, 2017 at 15:56
  • How can I loop only once and call the result for different x? What is the pythonic solution? - there is no even mathematical solution for this. Perhaps you can "hide" the loop, but not to avoid it. Commented Aug 11, 2017 at 16:01
  • NumPy also has a method that handles evaluating polynomials: docs.scipy.org/doc/numpy-1.12.0/reference/generated/… Commented Aug 11, 2017 at 16:06

4 Answers 4

1

Python cannot outwit mathematics. The only optimization that comes to mind is avoiding the calculation of terms you multiply by zero anyway:

def poly(x, order=(1, 0, 1)): res = 0 for i, o in enumerate(order): if o: res += o * x**i return res 

As one-liner:

def poly2(x, order=(1, 0, 1)): return sum(o * x**i for i, o in enumerate(order) if o) 
Sign up to request clarification or add additional context in comments.

Comments

1

Taking the suggestion of @Eugene Sh the repeated raising of powers can be eliminated:

xx = 1 def poly(x, order): global xx xx = 1 def f(x, o): global xx ret = xx * o xx *= x return ret return sum(f(x,o) for o in order) 

Comments

1

Code #1: sum for loop (slow)

def poly(x,order=[1,0,1]) : return sum([o*x**i for i,o in enumerate(order)]) 

Example:

poly(2,order=[2,0,2])

>> 10 >> Execution time: 5.29289245605e-05 

Code #2: Sum map (faster)

def poly(x,order=[1,0,1]) : return sum(map(lambda (i,o): o*x**i,enumerate(order))) 

Example:

poly(2,order=[2,0,2])

>> 10 >> Execution time: 3.00407409668e-05 

6 Comments

How is it answering the question?
@EugeneSh. How is it not?
The question is How can I loop only once and call the result for different x?
As far as I am aware you can't avoid the loop, I have obfuscated by using a map, so I answered the second part What is the pythonic solution?
So the first part of your comment is pretty much the answer to the question. Everything else is just side notes.
|
1
def make_poly(order): expression = '' for i, o in enumerate(order): if o: if expression: expression += ' + ' multiplier = '%d * ' % o if o > 1 else '' if i == 0: expression += str(o) elif i == 1: expression += multiplier + 'x' else: expression += multiplier + 'x**%d' % i loc = {} exec('def f(x):\n return ' + expression, {}, loc) return loc['f'] 

This creates an expression from the passed list, removing all terms that are zero and other redundant operations. Then exec is used to create a function which is returned.

>>> poly = make_poly([1, 0, 1]) >>> poly(5) 26 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.