Skip to content

Commit

Permalink
Swap math.pow with self.pow
Browse files Browse the repository at this point in the history
Before this commit, `pow` was the only binary function that doesn't use the
corresponding operator but calls `pow` in `math`. This commit defines a `pow`
function that invokes the corresponding operator (**).

Using ** is preferable because it is slightly faster and preservers
integers (see,
https://www.semicolonworld.com/question/56223/exponentials-in-python-x-y-vs-math-pow-x-y).
Moreover, it improves type compatibility, since now the function works with
user-defined classes (as long as they have a __pow__ method), `math.pow` only
supports numbers.
  • Loading branch information
Sbozzolo committed Jul 29, 2021
1 parent 12740ff commit c6102c3
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 12 deletions.
7 changes: 5 additions & 2 deletions py_expression_eval/__init__.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,9 @@ def mul(self, a, b):
def div(self, a, b):
return a / b

def pow(self, a, b):
return a ** b

def mod(self, a, b):
return a % b

Expand Down Expand Up @@ -374,8 +377,8 @@ def __init__(self, string_literal_quotes = ("'", "\"")):
'*': self.mul,
'/': self.div,
'%': self.mod,
'^': math.pow,
'**': math.pow,
'^': self.pow,
'**': self.pow,
',': self.append,
'||': self.concat,
"==": self.equal,
Expand Down
20 changes: 10 additions & 10 deletions py_expression_eval/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ def test_parser(self):
self.assertExactEqual(parser.parse('2 * 3').evaluate({}), 6)
self.assertExactEqual(parser.parse(u'2 \u2219 3').evaluate({}), 6)
self.assertExactEqual(parser.parse(u'2 \u2022 3').evaluate({}), 6)
self.assertExactEqual(parser.parse('2 ^ x').evaluate({'x': 3}), 8.0)
self.assertExactEqual(parser.parse('2 ** x').evaluate({'x': 3}), 8.0)
self.assertExactEqual(parser.parse('2 ^ x').evaluate({'x': 3}), 8)
self.assertExactEqual(parser.parse('2 ** x').evaluate({'x': 3}), 8)
self.assertExactEqual(parser.parse('-1.E2 ** x + 2.0E2').evaluate({'x': 1}), 100.0)
self.assertEqual(parser.parse('x < 3').evaluate({'x': 3}), False)
self.assertEqual(parser.parse('x < 3').evaluate({'x': 2}), True)
Expand All @@ -54,14 +54,14 @@ def test_parser(self):
self.assertExactEqual(parser.parse('2 * x + 1').evaluate({'x': 3}), 7)
self.assertExactEqual(parser.parse('2 + 3 * x').evaluate({'x': 4}), 14)
self.assertExactEqual(parser.parse('(2 + 3) * x').evaluate({'x': 4}), 20)
self.assertExactEqual(parser.parse('2-3^x').evaluate({'x': 4}), -79.0)
self.assertExactEqual(parser.parse('-2-3^x').evaluate({'x': 4}), -83.0)
self.assertExactEqual(parser.parse('-3^x').evaluate({'x': 4}), -81.0)
self.assertExactEqual(parser.parse('(-3)^x').evaluate({'x': 4}), 81.0)
self.assertExactEqual(parser.parse('2-3**x').evaluate({'x': 4}), -79.0)
self.assertExactEqual(parser.parse('-2-3**x').evaluate({'x': 4}), -83.0)
self.assertExactEqual(parser.parse('-3**x').evaluate({'x': 4}), -81.0)
self.assertExactEqual(parser.parse('(-3)**x').evaluate({'x': 4}), 81.0)
self.assertExactEqual(parser.parse('2-3.0^x').evaluate({'x': 4}), -79.0)
self.assertExactEqual(parser.parse('-2-3.0^x').evaluate({'x': 4}), -83.0)
self.assertExactEqual(parser.parse('-3^x').evaluate({'x': 4}), -81)
self.assertExactEqual(parser.parse('(-3)^x').evaluate({'x': 4}), 81)
self.assertExactEqual(parser.parse('2-3**x').evaluate({'x': 4}), -79)
self.assertExactEqual(parser.parse('-2-3**x').evaluate({'x': 4}), -83)
self.assertExactEqual(parser.parse('-3.0**x').evaluate({'x': 4}), -81.0)
self.assertExactEqual(parser.parse('(-3.0)**x').evaluate({'x': 4}), 81.0)
self.assertExactEqual(parser.parse('2*x + y').evaluate({'x': 4, 'y': 1}), 9)
self.assertEqual(parser.parse("x||y").evaluate({'x': 'hello ', 'y': 'world'}), 'hello world')
self.assertEqual(parser.parse("'x'||'y'").evaluate({}), 'xy')
Expand Down

0 comments on commit c6102c3

Please sign in to comment.