Oven logo

Oven

Published

Python Mathematical Expression Evaluator

pip install py-expression-eval

Package Downloads

Weekly DownloadsMonthly Downloads

Project URLs

Requires Python

Dependencies

    Python Mathematical Expression Evaluator

    Build Status

    PyPi version PyPi downloads

    Coverage Status

    Based on js-expression-eval, by Matthew Crumley ([email protected], http://silentmatt.com/) https://github.com/silentmatt/js-expression-eval

    Ported to Python and modified by @cansadadeserfeliz.

    You are free to use and modify this code in anyway you find useful. Please leave this comment in the code to acknowledge its original source. If you feel like it, I enjoy hearing about projects that use my code, but don't feel like you have to let me know or ask permission.

    Installation

    pip install py_expression_eval
    

    Tests

    python setup.py test
    

    Documentation

    All the classes and methods of py-expression-eval were written as similar as possible to their analogues from js-expression-eval to make it easier to use for validation on back-end side.

    Parser

    Parser is the main class of the library that contains the methods to parse, evaluate and simplify mathematical expressions. In order to use the library you need to create an instance of this class:

    > from py_expression_eval import Parser
    > parser = Parser()
    

    Once you instantiated Parser class, you can create Expression object using parse method:

    > parser.parse('2 * 3')
    Out: <py_expression_eval.Expression instance at 0x7f40cc4e5ef0>
    

    Parser.Expression

    evaluate() takes a dictionary with variables as a parameter and returns the value of the expression:

    > parser.parse('2 * 3').evaluate({})
    Out: 6
    > parser.parse('2 * 3.0').evaluate({})
    Out: 6.0
    > parser.parse('2 * x').evaluate({'x': 7})
    Out: 14
    > parser.parse('2 * x').evaluate({'x': 7.0})
    Out: 14.0
    

    substitute() creates a new expression where specified variables are replaces with a new expression. For example, to replace x with 3 + x in 2 * x expression we use the following code:

    > parser.parse('2 * x').substitute('x', '3 + x').toString()
    Out: '(2*(3+x))'
    

    variables() returns a list of the variables for the expression:

    > parser.parse('2 * x + y').variables()
    Out: ['x', 'y']
    

    simplify() simplifies the expression. For example,

    > parser.parse('2 * 3 * x + y').simplify({}).toString()
    Out: '((6*x)+y)'
    > parser.parse('2 * 3 * x + y').simplify({'x': -1}).toString()
    Out: '(-6+y)'
    > parser.parse('cos(PI) + x').simplify({}).toString()
    Out: '(-1.0+x)'
    

    toString() converts the expression to a string.

    Available operators, constants and functions

    ExpressionExampleOutput
    +parser.parse('2 + 2').evaluate({})4
    -parser.parse('3 - 1').evaluate({})2
    *parser.parse('2 * 3').evaluate({})6
    /parser.parse('5 / 2').evaluate({})2.5
    %parser.parse('5 % 2').evaluate({})1
    ^parser.parse('5 ^ 2').evaluate({})25.0
    PIparser.parse('PI').evaluate({})3.141592653589793
    Eparser.parse('E').evaluate({})2.718281828459045
    sin(x)parser.parse('sin(0)').evaluate({})0.0
    cos(x)parser.parse('cos(PI)').evaluate({})- 1.0
    tan(x)parser.parse('tan(0)').evaluate({})0.0
    asin(x)parser.parse('asin(0)').evaluate({})0.0
    acos(x)parser.parse('acos(-1)').evaluate({})3.141592653589793
    atan(x)parser.parse('atan(PI)').evaluate({})1.2626272556789118
    log(x)parser.parse('log(1)').evaluate({})0.0
    log(x, base)parser.parse('log(16, 2)').evaluate({})4.0
    abs(x)parser.parse('abs(-1)').evaluate({})1
    ceil(x)parser.parse('ceil(2.7)').evaluate({})3.0
    floor(x)parser.parse('floor(2.7)').evaluate({})2.0
    round(x)parser.parse('round(2.7)').evaluate({})3.0
    exp(x)parser.parse('exp(2)').evaluate({})7.38905609893065
    andparser.parse('a and b').evaluate({'a':True, 'b':True})True
    orparser.parse('a or b').evaluate({'a':True, 'b':True})True
    xorparser.parse('a xor b').evaluate({'a':True, 'b':True})False
    notparser.parse('a and not b').evaluate({'a':True, 'b':True})False
    inparser.parse('1 in (1,2,3)').evaluate({})True

    Examples

    from py_expression_eval import Parser
    
    parser = Parser()
    parser.parse('2 * 3').evaluate({})  # 6
    parser.parse('2 ^ x').evaluate({'x': 3})  # 8.0
    parser.parse('2 * x + 1').evaluate({'x': 3})  # 7
    parser.parse('2 + 3 * x').evaluate({'x': 4})  # 14
    parser.parse('(2 + 3) * x').evaluate({'x': 4}) # 20
    parser.parse('2-3^x').evaluate({'x': 4})  # -79.0
    parser.parse('-2-3^x').evaluate({'x': 4})  # -83.0
    parser.parse('-3^x').evaluate({'x': 4})  # -81.0
    parser.parse('(-3)^x').evaluate({'x': 4})  # 81.0
    parser.parse('2*x + y').evaluate({'x': 4, 'y': 1})  # 9
    parser.parse('round(log(2.7))').evaluate({}) # 1.0
    
    # substitute
    expr = parser.parse('2 * x + 1')
    expr2 = expr.substitute('x', '4 * x')  # ((2*(4*x))+1)
    expr2.evaluate({'x': 3})  # 25
    
    # simplify
    expr = parser.parse('x * (y * atan(1))').simplify({'y': 4})
    expr.toString()  # x*3.141592
    expr.evaluate({'x': 2})  # 6.283185307179586
    
    # get variables
    expr = parser.parse('x * (y * atan(1))')
    expr.variables()  # ['x', 'y']
    expr.simplify({'y': 4}).variables()  # ['x']
    

    Available operations

    from py_expression_eval import Parser
    
    parser = Parser()
    parser.parse('2 + 3').evaluate({})  # 5
    parser.parse('2 - 3').evaluate({})  # -1
    parser.parse('2 * 3').evaluate({})  # 6
    parser.parse('2 / 3').evaluate({})  # 0.6666666666666666
    parser.parse('2 % 3').evaluate({})  # 2
    parser.parse('-2').evaluate({})  # -2
    parser.parse('abs(-2)').evaluate({}) # 2
    
    parser.parse('ceil(1.4)').evaluate({})  # 2.0
    parser.parse('floor(1.4)').evaluate({})  # 1.0
    parser.parse('round(1.4)').evaluate({})  # 1.0
    
    parser.parse('2^3').evaluate({})  # 8.0
    parser.parse('sqrt(16)').evaluate({}) # 4.0
    
    parser.parse('sin(3.14)').evaluate({})  # 0.0015926529164868282
    parser.parse('cos(3.14)').evaluate({})  # -0.9999987317275395
    parser.parse('tan(3.14)').evaluate({})  # -0.0015926549364072232
    
    parser.parse('asin(1)').evaluate({})  # 1.5707963267948966
    parser.parse('acos(1)').evaluate({})  # 0.0
    parser.parse('atan(1)').evaluate({})  # 0.7853981633974483
    
    parser.parse('log(2.7)').evaluate({})  # 0.9932517730102834
    parser.parse('exp(1)').evaluate({})  # 2.718281828459045
    
    parser.parse('log(E)').evaluate({})  # 1.0
    parser.parse('cos(PI)').evaluate({})  # -1.0
    
    parser.parse('x||y').evaluate({'x': 2, 'y': 3})  # '23'
    
    parser.parse('num in (1,2,3)').evaluate({'num': 1})  # True
    parser.parse('"word" in "word in sentence"').evaluate({})  # True
    

    Upload package to PyPi

    Generating distribution archives

    python3 setup.py sdist bdist_wheel
    

    Upload distribution

    ls -a dist/
    twine upload dist/py_expression_eval-0.3.9*
    

    Check on: https://pypi.org/project/py-expression-eval/0.3.9/

    More details: https://packaging.python.org/tutorials/packaging-projects/