#! /usr/bin/env python # -*- coding: utf-8 -*- # vim:fenc=utf-8 # # Copyright © 2017 lafrite # # Distributed under terms of the MIT license. """ Tokens representing interger and decimal """ from decimal import Decimal as _Decimal from .token import Token from ...core.arithmetic import gcd from ...core.MO import MO, MOnumber from ...core.MO.fraction import MOFraction __all__ = ["Integer", "Decimal", "Fraction"] class Integer(Token): """ Token representing a integer :example: >>> Integer(4) >>> a = MOnumber(4) >>> Integer.from_mo(a) """ def __init__(self, a, name="", ancestor=None): if not isinstance(a, MO): if not isinstance(a, int): raise TypeError mo = MOnumber(a) else: mo = a Token.__init__(self, mo, name, ancestor) self._mathtype = "entier" @classmethod def from_mo(cls, mo, name="", ancestor=None): if not isinstance(mo, MOnumber): raise TypeError if not isinstance(mo.value, int): raise TypeError return cls(mo, name, ancestor) class Decimal(Token): """ Token representing a decimal :example: >>> Decimal("4.3") >>> Decimal(3.3) >>> Decimal(_Decimal("2.3")) """ def __init__(self, a, name="", ancestor=None): if not isinstance(a, MO): if isinstance(a, _Decimal): mo = MOnumber(a) elif isinstance(a, (str, float)): mo = MOnumber(_Decimal(a)) else: raise TypeError else: mo = a self._mathtype = "décimal" Token.__init__(self, mo, name, ancestor) @classmethod def from_mo(cls, mo, name="", ancestor=None): if not isinstance(mo, MOnumber): raise TypeError if not isinstance(mo.value, _Decimal): raise TypeError return cls(mo, name, ancestor) class Fraction(Token): """ Token representing a fraction of numbers :example: >>> Fraction("3/4") """ def __init__(self, a, name="", ancestor=None): if not isinstance(a, MO): if isinstance(a, str): num, denom = a.split("/") mo = MOFraction(int(num), int(denom)) else: raise TypeError else: mo = a self._mathtype = "fraction" Token.__init__(self, mo, name, ancestor) @classmethod def from_mo(cls, mo, name="", ancestor=None): if not isinstance(mo, MOFraction): raise TypeError if not isinstance(mo._numerator, MOnumber): raise TypeError if not isinstance(mo._denominator, MOnumber): raise TypeError return cls(mo, name, ancestor) @property def numerator(self): """ Get numerator of the fraction :example: >>> a = Fraction("3/4") >>> a.numerator """ return Integer(self._mo.numerator) @property def denominator(self): """ Get denominator of the fraction :example: >>> a = Fraction("3/4") >>> a.denominator """ return Integer(self._mo.denominator) @property def decimal(self): """ return decimal approximation of the fraction :example: >>> f = Fraction("3/4") >>> f.decimal >>> f = Fraction("1/3") >>> f.decimal """ return Decimal(self._mo._value) @property def simplified(self): """ Get the irreductible version of self :example: >>> f = Fraction("3/4") >>> f.simplified >>> f = Fraction("12/9") >>> f.simplified >>> f = Fraction("12/4") >>> f.simplified """ simplified = self._mo.simplified() if isinstance(simplified, MOnumber): return Integer(simplified) return Fraction(simplified) def simplify(self): """ Itself or its simplified version :example: >>> f = Fraction("12/8") >>> fs = f.simplify() >>> for i in fs.explain(): ... print(i) 12 / 8 3 / 2 >>> f = Fraction("5/8") >>> fs = f.simplify() >>> for i in fs.explain(): ... print(i) 5 / 8 """ simplified = self.simplified try: if self.numerator == simplified.numerator: return self except AttributeError: pass simplified._ancestor = self return simplified # ----------------------------- # Reglages pour 'vim' # vim:set autoindent expandtab tabstop=4 shiftwidth=4: # cursor: 16 del