Rushy Panchal - 3 months ago 8
Python Question

# Calculating Integrals: One-liner solution?

I was working on a program to find the integral of a function, where the user specifies the amount of rectangles, the start, and the stop.

NOTE: I am using left-end points of the rectangles.

I have the function working perfectly (at least, it seems to be perfect). However, I wanted to see if I could write a one-liner for it, but not sure how because I'm using

`eval()`
. Here is my original code:

``````def integral(function, n=1000, start=0, stop=100):
"""Returns integral of function from start to stop with 'n' rectangles"""
increment, rectangles, x = float((stop - start)) / n, [], start
while x <= stop:
num = eval(function)
rectangles.append(num)
if x >= stop: break
x += increment
return increment * sum(rectangles)
``````

This works fine:

``````>>> integral('x**2')
333833.4999999991
``````

`1000000/3`
, so my function gives a pretty nice estimate (for only 1000 rectangles).

My attempt at a one-liner:

``````def integral2(function, n=1000, start=0, stop=100): rectangles = [(float(x) / n) for x in range(start*n, (stop*n)+1)]; return (float((stop-start))/n) * sum([eval(function) for x in rectangles])
``````

However, this isn't a truly a one-liner since I'm using a semi-colon. Also, it's a bit slower (takes a few seconds longer, which is pretty significant) and gives the wrong answer:

``````>>> integral2('x**2')
33333833.334999967
``````

So, is it possible to use a one-liner solution for this function? I wasn't sure how to implement
`eval()`
and
`float(x)/n`
in the same list comprehension.
`float(x)/n`
achieves a virtual 'step' in the
`range`
function.

Thanks!

``````def integral2(function, n=1000, start=0, stop=100): return (float(1)/n) * sum([eval(function) for x in [(float(x) / n) for x in range(start*n, (stop*n)+1)]])
``````

Note that there is a big difference between `integral` and `integral2`: `integral2` makes `(stop*n)+1-(start*n)` rectangles, while `integral` only makes `n` rectangles.

``````In [64]: integral('x**2')
Out[64]: 333833.4999999991
In [68]: integral2('x**2')
Out[68]: 333338.33334999956
``````

``````In [69]: %timeit integral2('x**2')
1 loops, best of 3: 704 ms per loop

In [70]: %timeit integral('x**2')
100 loops, best of 3: 7.32 ms per loop
``````

Perhaps a more comparable translation of `integral` would be:

``````def integral3(function, n=1000, start=0, stop=100): return (float(stop-start)/n) * sum([eval(function) for x in [start+(i*float(stop-start)/n) for i in range(n)]])

In [77]: %timeit integral3('x**2')
100 loops, best of 3: 7.1 ms per loop
``````

Of course, it should go with say that there is no purpose for making this a one-liner other than (perverse?) amusement :)

Source (Stackoverflow)