diff --git a/pymath/expression.py b/pymath/expression.py index b5cef2f..44dc9e9 100644 --- a/pymath/expression.py +++ b/pymath/expression.py @@ -28,6 +28,46 @@ class Expression(object): def set_default_render(cls): cls.set_render(cls.DEFAULT_RENDER) + @classmethod + def tmp_render(cls, render = lambda _,x:Expression(x)): + """ Create a container in which Expression render is temporary modify + + The default temporary render is Expression in order to perform calculus inside numbers + + >>> exp = Expression("2*3/5") + >>> print(exp) + \\frac{ 2 \\times 3 }{ 5 } + >>> for i in exp.simplify(): + ... print(i) + \\frac{ 2 \\times 3 }{ 5 } + \\frac{ 6 }{ 5 } + >>> with Expression.tmp_render(): + ... for i in exp.simplify(): + ... i + < Expression [2, 3, '*', 5, '/']> + < Expression [6, 5, '/']> + < Fraction 6 / 5> + + >>> with Expression.tmp_render(txt): + ... for i in exp.simplify(): + ... print(i) + 2 * 3 / 5 + 6 / 5 + >>> for i in exp.simplify(): + ... print(i) + \\frac{ 2 \\times 3 }{ 5 } + \\frac{ 6 }{ 5 } + + """ + class TmpRenderEnv(object): + def __enter__(self): + self.old_render = Expression.get_render() + Expression.set_render(render) + + def __exit__(self, type, value, traceback): + Expression.set_render(self.old_render) + return TmpRenderEnv() + @classmethod def random(self, form="", conditions=[], val_min = -10, val_max=10): """Create a random expression from form and with conditions @@ -299,10 +339,10 @@ def test(exp): print("\n") if __name__ == '__main__': - render = lambda _,x : str(x) - Expression.set_render(render) - exp = Expression("1/2 - 4") - print(list(exp.simplify())) + #render = lambda _,x : str(x) + #Expression.set_render(render) + #exp = Expression("1/2 - 4") + #print(list(exp.simplify())) #Expression.set_render(txt) #exp = "2 ^ 3 * 5" @@ -386,8 +426,8 @@ if __name__ == '__main__': #for i in exp.simplify(): # print(i) - #import doctest - #doctest.testmod() + import doctest + doctest.testmod() # ----------------------------- # Reglages pour 'vim' diff --git a/pymath/fraction.py b/pymath/fraction.py index 20365d1..4b9ff3e 100644 --- a/pymath/fraction.py +++ b/pymath/fraction.py @@ -119,13 +119,13 @@ class Fraction(object): >>> f = Fraction(1, 2) >>> g = Fraction(2, 3) >>> f + g - [< Expression [1, 3, '*', 2, 3, '*', '/', 2, 2, '*', 3, 2, '*', '/', '+']>, < Expression [3, 4, '+', 6, '/']>, < Fraction 7 / 6>] + [< Expression [1, 3, '*', 2, 3, '*', '/', 2, 2, '*', 3, 2, '*', '/', '+']>, < Expression [3, 6, '/', 4, 6, '/', '+']>, < Expression [< Fraction 3 / 6>, < Fraction 4 / 6>, '+']>, < Expression [3, 4, '+', 6, '/']>, < Expression [7, 6, '/']>, < Fraction 7 / 6>] >>> f + 2 - [< Expression [1, 1, '*', 2, 1, '*', '/', 2, 2, '*', 1, 2, '*', '/', '+']>, < Expression [1, 4, '+', 2, '/']>, < Fraction 5 / 2>] + [< Expression [1, 1, '*', 2, 1, '*', '/', 2, 2, '*', 1, 2, '*', '/', '+']>, < Expression [1, 2, '/', 4, 2, '/', '+']>, < Expression [< Fraction 1 / 2>, < Fraction 4 / 2>, '+']>, < Expression [1, 4, '+', 2, '/']>, < Expression [5, 2, '/']>, < Fraction 5 / 2>] >>> f = Fraction(3, 4) >>> g = Fraction(5, 4) >>> f + g - [< Expression [3, 5, '+', 4, '/']>, < Fraction 8 / 4>, 2] + [< Expression [3, 5, '+', 4, '/']>, < Expression [8, 4, '/']>, 2] """ @@ -134,31 +134,22 @@ class Fraction(object): number = self.convert2fraction(other) - steps = [] - if self._denom == number._denom: com_denom = self._denom num1 = self._num num2 = number._num + exp = Expression([num1, num2, op.add, com_denom, op.div]) + else: gcd_denom = gcd(self._denom, number._denom) coef1 = number._denom // gcd_denom coef2 = self._denom // gcd_denom - steps.append(Expression([self._num, coef1, op.mul, self._denom, coef1, op.mul, op.div, number._num, coef2, op.mul, number._denom, coef2, op.mul, op.div,op.add]) ) + exp = Expression([self._num, coef1, op.mul, self._denom, coef1, op.mul, op.div, number._num, coef2, op.mul, number._denom, coef2, op.mul, op.div,op.add]) - com_denom = self._denom * coef1 - num1 = self._num * coef1 - num2 = number._num * coef2 - - steps.append(Expression([num1, num2, op.add, com_denom, op.div])) - - num = num1 + num2 - - ans_frac = Fraction(num, com_denom) - steps.append(ans_frac) - steps += ans_frac.simplify() + with Expression.tmp_render(): + steps = list(exp.simplify()) return steps @@ -176,7 +167,7 @@ class Fraction(object): >>> f = Fraction(1, 2) >>> g = Fraction(2, 3) >>> f - g - [< Expression [1, 3, '*', 2, 3, '*', '/', 2, 2, '*', 3, 2, '*', '/', '-']>, < Expression [3, 4, '-', 6, '/']>, < Fraction -1 / 6>] + [< Expression [1, 3, '*', 2, 3, '*', '/', 2, 2, '*', 3, 2, '*', '/', '-']>, < Expression [3, 6, '/', 4, 6, '/', '-']>, < Expression [< Fraction 3 / 6>, < Fraction 4 / 6>, '-']>, < Expression [3, 4, '-', 6, '/']>, < Expression [-1, 6, '/']>, < Fraction -1 / 6>] """ if other == 0: @@ -184,31 +175,22 @@ class Fraction(object): number = self.convert2fraction(other) - steps = [] - if self._denom == number._denom: com_denom = self._denom num1 = self._num num2 = number._num + exp = Expression([num1, num2, op.sub, com_denom, op.div]) + else: gcd_denom = gcd(self._denom, number._denom) coef1 = number._denom // gcd_denom coef2 = self._denom // gcd_denom - steps.append(Expression([self._num, coef1, op.mul, self._denom, coef1, op.mul, op.div, number._num, coef2, op.mul, number._denom, coef2, op.mul, op.div,op.sub])) + exp = Expression([self._num, coef1, op.mul, self._denom, coef1, op.mul, op.div, number._num, coef2, op.mul, number._denom, coef2, op.mul, op.div,op.sub]) - com_denom = self._denom * coef1 - num1 = self._num * coef1 - num2 = number._num * coef2 - - steps.append(Expression([num1, num2, op.sub, com_denom, op.div])) - - num = num1 - num2 - - ans_frac = Fraction(num, com_denom) - steps.append(ans_frac) - steps += ans_frac.simplify() + with Expression.tmp_render(): + steps = list(exp.simplify()) return steps @@ -234,7 +216,11 @@ class Fraction(object): """ f = Fraction(-self._num, self._denom) - return [f] + f.simplify() + + with Expression.tmp_render(): + steps = [f] + f.simplify() + + return steps def __mul__(self, other): """ overload * @@ -242,13 +228,13 @@ class Fraction(object): >>> f = Fraction(1, 2) >>> g = Fraction(2, 3) >>> f*g - [< Expression [1, 1, 2, '*', '*', 1, 2, '*', 3, '*', '/']>, < Fraction 1 / 3>] + [< Expression [1, 1, 2, '*', '*', 1, 2, '*', 3, '*', '/']>, < Expression [1, 2, '*', 2, 3, '*', '/']>, < Expression [2, 6, '/']>, < Expression [1, 2, '*', 3, 2, '*', '/']>, < Fraction 1 / 3>] >>> f * 0 [0] >>> f*1 [< Fraction 1 / 2>] >>> f*4 - [< Expression [1, 2, '*', 2, '*', 1, 2, '*', '/']>, < Fraction 2 / 1>, 2] + [< Expression [1, 2, '*', 2, '*', 1, 2, '*', '/']>, < Expression [2, 2, '*', 2, '/']>, < Expression [4, 2, '/']>, 2] """ steps = [] @@ -258,6 +244,8 @@ class Fraction(object): elif other == 1: return [self] + # TODO: Changer dans le cas où il y a trop de 1 |dim. déc. 28 10:44:10 CET 2014 + elif type(other) == int: gcd1 = gcd(other, self._denom) if gcd1 != 1: @@ -266,10 +254,8 @@ class Fraction(object): else: num = [self._num, other, op.mul] denom = [self._denom] - steps.append(Expression(num + denom + [op.div])) - num = int(self._num * other / gcd1) - denom = int(self._denom / gcd1) + exp = Expression(num + denom + [op.div]) else: number = self.convert2fraction(other) @@ -291,14 +277,10 @@ class Fraction(object): denom1 = [self._denom] - steps.append(Expression(num1 + num2 + [ op.mul] + denom1 + denom2 + [op.mul, op.div])) + exp = Expression(num1 + num2 + [ op.mul] + denom1 + denom2 + [op.mul, op.div]) - num = int(self._num * number._num / (gcd1 * gcd2)) - denom = int(self._denom * number._denom / (gcd1 * gcd2)) - - ans_frac = Fraction(num, denom) - steps.append(ans_frac) - steps += ans_frac.simplify() + with Expression.tmp_render(): + steps = list(exp.simplify()) return steps @@ -334,10 +316,10 @@ class Fraction(object): >>> f**1 [< Fraction 3 / 4>] >>> f**3 - [< Expression [3, 3, '^', 4, 3, '^', '/']>, < Fraction 27 / 64>] + [< Expression [3, 3, '^', 4, 3, '^', '/']>, < Expression [27, 64, '/']>, < Fraction 27 / 64>] >>> f = Fraction(6, 4) >>> f**3 - [< Expression [6, 3, '^', 4, 3, '^', '/']>, < Fraction 216 / 64>, < Expression [27, 8, '*', 8, 8, '*', '/']>, < Fraction 27 / 8>] + [< Expression [6, 3, '^', 4, 3, '^', '/']>, < Expression [216, 64, '/']>, < Expression [27, 8, '*', 8, 8, '*', '/']>, < Fraction 27 / 8>] """ if not type(power) == int: @@ -348,10 +330,9 @@ class Fraction(object): elif power == 1: return [self] else: - steps = [Expression([self._num, power, op.pw, self._denom, power, op.pw, op.div])] - ans_frac = Fraction(self._num ** power, self._denom ** power) - steps.append(ans_frac) - steps += ans_frac.simplify() + exp = Expression([self._num, power, op.pw, self._denom, power, op.pw, op.div]) + with Expression.tmp_render(): + steps = list(exp.simplify()) return steps def __xor__(self, power): @@ -364,10 +345,10 @@ class Fraction(object): >>> f^1 [< Fraction 3 / 4>] >>> f^3 - [< Expression [3, 3, '^', 4, 3, '^', '/']>, < Fraction 27 / 64>] + [< Expression [3, 3, '^', 4, 3, '^', '/']>, < Expression [27, 64, '/']>, < Fraction 27 / 64>] >>> f = Fraction(6, 4) >>> f^3 - [< Expression [6, 3, '^', 4, 3, '^', '/']>, < Fraction 216 / 64>, < Expression [27, 8, '*', 8, 8, '*', '/']>, < Fraction 27 / 8>] + [< Expression [6, 3, '^', 4, 3, '^', '/']>, < Expression [216, 64, '/']>, < Expression [27, 8, '*', 8, 8, '*', '/']>, < Fraction 27 / 8>] """ diff --git a/pymath/polynom.py b/pymath/polynom.py index c2efb91..6a8f10a 100644 --- a/pymath/polynom.py +++ b/pymath/polynom.py @@ -291,19 +291,15 @@ class Polynom(object): # On converti en Expression coef_exp = Expression(postfix_add) - old_render = Expression.get_render() - Expression.set_render(lambda _,x:Expression(x)) - coef_steps = list(coef_exp.simplify()) - Expression.set_render(old_render) + with Expression.tmp_render(): + coef_steps = list(coef_exp.simplify()) #print('\t 1.coef_steps -> ', coef_steps) elif type(coef) == Expression: - old_render = Expression.get_render() - Expression.set_render(lambda _,x:Expression(x)) - coef_steps = list(coef.simplify()) - Expression.set_render(old_render) + with Expression.tmp_render(): + coef_steps = list(coef.simplify()) #print('\t 2.coef_steps -> ', coef_steps) @@ -524,12 +520,12 @@ def test(p,q): if __name__ == '__main__': #from .fraction import Fraction - Expression.set_render(txt) - p = Polynom([10, -5]) - q = Polynom([3, -9]) - print(p-q) - for i in p-q: - print(i) + with Expression.tmp_render(txt): + p = Polynom([10, -5]) + q = Polynom([3, -9]) + print(p-q) + for i in p-q: + print(i) import doctest