Python-symbolic/python_symb/fractions.py
2023-07-31 04:42:40 +02:00

132 lines
3.4 KiB
Python

from __future__ import annotations
from typing import Iterable, Generator
from tools import gcd
class Fractions:
"""
Should represent a fraction not a division
"""
__slots__ = ['num', 'den']
__match_args__ = ("num", "den")
#todo check if num and den are part of a domain, so a/b as a meaning a gcd work well
#todo implement __iadd__ etc... if performance needed
def __init__(self, *args):
match args:
case num, den:
self.num = num
self.den = den
case x, :
self.num = x
self.den = 1
def __repr__(self):
return f'Fractions({self.num}, {self.den})'
def simplify_gcd(self):
"""Simplify fraction by diving num and den by their gcd
return None"""
match self.num, self.den:
case int(num), int(den):
gcd_ = gcd(num, den)
self.num //= gcd_
self.den //= gcd_
# can be completed with others objects that support gcd like polynomials etc...
def simplify_to_num(self):
"""from frac(a, 1) return a."""
if self.den == 1:
return self.num
def simplify_nested(self, rec=True):
"""simplify nested fractions.
Fractions(1, Fractions(1, Fractions(1, Fractions(1, 2)))) -> Fractions(2, 1)
For one simplification step put rec=False
return None"""
def aux(fract):
match fract:
case Fractions(Fractions(a, b), Fractions(c, d)):
fract.num = a * d
fract.den = b * c
case Fractions(num, Fractions(a, b)):
fract.num = num * b
fract.den = a
case Fractions(Fractions(a, b), den):
fract.num = a
fract.den = b * den
if rec:
num, den = self.num, self.den
if isinstance(num, Fractions) or isinstance(den, Fractions):
aux(fract)
aux(self)
def simplify_all_(self):
self.simplify_gcd()
self.simplify_nested()
res = self.simplify_to_num()
if res:
return res
return self
def __add__(self, other):
match other:
case int(x):
return Fractions(self.num + self.den*x, self.den)
case Fractions(num, den):
result = Fractions(self.num*den + num*self.den, self.den*den)
return result
return ValueError
def __radd__(self, other):
return other + self
def __neg__(self):
return Fractions(-self.num, self.den)
def __mul__(self, other):
match other:
case int(x):
return Fractions(self.num*x, self.den)
case Fractions(num, den):
result = Fractions(self.num*num, self.den*den)
return result
return ValueError
def __rmul__(self, other):
return self*other
def __truediv__(self, other):
match other:
case int(x):
return Fractions(self.num, self.den*x)
case Fractions(num, den):
return Fractions(self.num*den, self.den*num)
def __rtruediv__(self, other):
res = self/other
return Fractions(res.den, res.num)
if __name__ == "__main__":
a = Fractions(1, 2)
a += 1
print(a)