Better way to evaluate mathematical expression in python? [duplicate] - python

This question already has answers here:
Evaluating a mathematical expression in a string
(14 answers)
Closed 9 years ago.
Say I have 50,000 lines of string that contain simple mathematical expression (only +,- operator involve e.g. 1+2+3+5). I know that it is handy to use eval() in Python to evaluate those strings. However, the program is not efficient enough. I ran the cProfile and found most of the bottleneck is from the eval function (around 2.5 secs in 50,000 lines case). I've tried to write my own evaluation parser but it perform even slower then the eval.
So, what I want to ask is if there are any way to fast evaluate mathematical expression strings or improve the performance of eval()? Third-party package cannot be used.
The original problem is like this
We have a string of digit like 1234567 and we can insert +,-,or nothing between the digits like 1+23-4+56-7. So there will be 3^(digit-1) combinations for a given number string
What I implement in Python to calculate and generate string like the following
import itertools
def gen_Eq(op, num):
temp = [None]*(2*len(num)-1)
temp[::2] = num
temp[1::2] = op
string = ''.join(temp)
return string
def cal_Eq(num_string):
op_list = tuple(itertools.product(['+','-',''],repeat=len(num_string)-1))
eq = list(map(gen_Eq,op_list,itertools.repeat(num_string,len(op_list))))
print map(eval,eq)

This approach is faster:
>>> import re
>>> split_numbers = re.compile(r'-?\d+').findall
>>> sum(int(x) for x in split_numbers('1+23-4+56-7'))
69
In my timings the sum expression takes 4.5 µs vs. 13 µs for eval('1+23-4+56-7')
Note, however, that it does not handle consecutive + and -, eg. 1-+2 or 1--2, or spaces: 1 - 2.

Related

what's the advantage of using operator function in Python? [duplicate]

This question already has answers here:
In what situation should the built-in 'operator' module be used in python?
(6 answers)
Closed 1 year ago.
from operator import add
n1 = add(2,3)
n2 = 2 + 3
Both return exactly the same number and I believe they also work in the same way. What are the advantages of using add() to calculate the sum of two numbers?
are there any cases where only one method is accepted?
Sometimes, you may want to pass the operator as a function somewhere, for example:
functools.reduce(operator.mul, [2,3,4,5]) # 120
You could, of course do something like:
functools.reduce(lambda x, y: x * y, [2,3,4,5])
but the operator reads better and is faster.

Python3 - solve math equations that are in string format [duplicate]

This question already has answers here:
Evaluating a mathematical expression in a string
(14 answers)
Closed 3 years ago.
Is there a way to solve math equations that are in string format?
For example, I have
x = 2
y = 3
equations_str = ('x+y', 'x-y')
and I want a function that will give
results = (5, -1)
I want to do this because I want to have the equations as titles of figures, so they need to be strings.
I'm aware that a similar question was asked for java, but I'm not familiar enough with java so translate it to python.
Thanks!
Look into eval() https://www.geeksforgeeks.org/eval-in-python/ You can write statements and execute them.
eval example (interactive shell):
>>> x = 1
>>> eval('x + 1')
2
>>> eval('x')
1
As Jam mentioned, you can do the following:
equations_str = (eval('x+y'), eval('x-y'))
The only way I can think of solving this problem is to take your equation, calculate it as a regular integer, and then convert it into a string using str(). Then you could put that result into an array before proceeding. The only thing is that this method won't work for large amounts, but if you only need a few, this should work. Hope this helps, Luke.
Try the sympify function of the sympy package. It lets you evaluate strings, but uses the eval function, so do not use it on unsanitized input.
Example:
>>> from sympy import sympify
>>> str_expr = "x**2 + 3*x - 1/2"
>>> expr = sympify(str_expr)
>>> expr
x**2 + 3*x - 1/2
>>> expr.subs(x, 2)
19/2

Code notes: Explaining the what is happening in the code [duplicate]

This question already has answers here:
What does Python's eval() do?
(12 answers)
Closed 4 years ago.
I am a newbie developer. I have used the code below but I would like to understand how the last line works, can someone please explain to me the last line return eval(((str(a)+"*")*b)[:-1]) of the code?
def power(a,b):
if b == 0:
return 1
else:
return eval(((str(a)+"*")*b)[:-1])
eval evaluates python code or lets Python program run Python code within itself.
example:
CODE:
a = 15
eval('print(a + 3)')
OUTPUT:
18
when you return the following
eval(((str(a)+"*")*b)[:-1])
what you basically doing is this( for example if you are computing power(2,5)):
str(a) -> changes the value of a to string. in this case "2"
str(a)+"*" -> concatinate the above string to the multiplication sign. now we have "2*"
(str(a)+"*")*b) -> duplicates the above string b times. That is "2*"+"2*"+"2*"+"2*"+"2*", that is five times and now you have "2*2*2*2*2*"
But as you can see there is an extra "*" at the end. To remove this one we use [:-1]. what this basically doing is select all except the last one. ":" basically means all.
so the final expression to be evaluated is "2*2*2*2*2". which is 2^5.
The best way is to use a**b for computing power. However, if you want to use eval then consider joining the string in this way: eval('*'.join(str(a)*b)). In this, str(a) will convert integer a to string a then *b will repeat the a b times and finally the '*'.join() will join all the a's together with * in between and create a string something like a*a*a*a. eval will then evaluate the string as if it is an expression.
return eval(((str(a)+"*")*b)[:-1])
is equivalent to
a_str=str(a) # convert a in STRING
a_star=a_str+"*" # concat the string a_str with "*"
a_repeted=a_star*b # repeat a_star "b" times
exp=(a_repeted)[:-1] # get all a_repeted car except the last on (ex 3*3*3*3 for a=3 and b=4)
res=eval(exp) # evalutate the expression
return res
it'is equivalent to (really better ;-) !) :
def power(a,b):
return a ** b
A terrible idea, as others have said - if you're a newbie, consider finding a better guide!
eval reads a string and evaluates it as if it were not (as if it is not in quotes). So we construct a string of a ** b (ie a^b), and ask Python to read it, then return all but the last character. Pretty pointless but there you go.
eval() is never a good idea to use. Read about its dangerous behaviour here.
You just need ** operator which is equivalent to ^ (raise to) operator you see in other languages:
def power(a,b):
return a ** b

Fast way of converting parts of a bit numpy array to base 10 [duplicate]

This question already has answers here:
Binary numpy array to list of integers?
(5 answers)
Closed 5 years ago.
Say I am given a numpy integer array of the form
a=np.array([0,0,0,1,1,0,1,0,1,0,1])
Now suppose I want to extract part of that array from positions i1:i2 and convert it to a base 10 representation. For instance, take i1=4 and i2=8. Then:
base_2=a[i1:i2] # base_2 = np.array([1,0,1,0])
And I would expect the function to return 10=2+8.
My question is the following : What is a fast way to achieve this in Python ?
Consider a function with the following signature:
def base_2_to_10_array(my_array,i1,i2):
return """your awesome answer here"""
One way (don't know if it is the fastest)
>>> a=np.array([0,0,0,1,1,0,1,0,1,0,1])
>>> int(''.join(map(str, a[4:8])), 2)
10
Another way, which I believe to be faster (benchmark), is:
def base_2_to_10_array(arr, i1, i2):
res = 0
for bit in arr[i1:i2][::-1]:
res = (res << 1) ^ bit
return res
This is probably faster because it is entirely binary operations (<< and ^), which are both fast (^ is faster because one of the operands is small, being 0 or 1).
percusse's answer is probably slower because of either mapping with str, or casting to int (might not be as optimized for binary).
type_none's is probably slower due to repeated calling of a lambda, multiplication instead of shifts and adding instead of oring.
Example benchmark results:
Size: 10
percusse: 0.016117284998472314
type_none: 0.004335935998824425
pycoder_3rd_fastest: 0.0028656079957727343
pycoder_2nd_fastest: 0.0033370210003340617
pycoder_fastest: 0.0031539250048808753
Size: 100
percusse: 0.13562769599957392
type_none: 0.04904397700011032
pycoder_3rd_fastest: 0.016703221001080237
pycoder_2nd_fastest: 0.021887271002924535
pycoder_fastest: 0.019885091001924593
Size: 1000
percusse: 1.358273936995829
type_none: 0.7615448830038076
pycoder_3rd_fastest: 0.18778558799385792
pycoder_2nd_fastest: 0.20695334099582396
pycoder_fastest: 0.18905453699699137
Size: 10000
percusse: 14.638380388998485
type_none: 7.554422806002549
pycoder_3rd_fastest: 5.3742733830004
pycoder_2nd_fastest: 2.2020759820006788
pycoder_fastest: 1.9534191700004158
Other attempts, one faster on shorter inputs, can be found in the benchmark link.
I used reduce here. Unlike other answers this doesn't need conversion to string.
from functools import reduce # no need for import in python2
import numpy as np
def arrayToInt(l):
return reduce(lambda x,y: (x<<1) + y, l)
a=np.array([0,0,0,1,1,0,1,0,1,0,1])
number = arrayToInt(a[4:8])
print(number)

How to convert '1+2' into an int in python [duplicate]

This question already has answers here:
Evaluating a mathematical expression in a string
(14 answers)
Closed 6 years ago.
For example if i have:
x = '12'
print(int(x))
would turn x into an integer from a string.
What if I have:
x = '1+2'
And I want 3 as my output, how would I go about it since + cannot be converted into an int directly?
Use literal_eval which is much more safer than using eval. literal_eval safely evaluates an expression node or a string containing a python expression.
import ast
x = ast.literal_eval('1+2')
You could use the eval function to accomplish this; however, it should be noted that allowing unsanitized input into the eval function can pose a significant security risk. Here's an example:
x = '1 + 2'
print(eval(x))
Here you can use eval.
The usage is eval(expression[, globals[, locals]]).
Therefore
eval('1+2')
3

Categories

Resources