School/.venv/lib/python3.9/site-packages/mathprolib/Fraction.py
Kristofers Solo 1e065cc4b2 Updated .venv
2021-11-22 17:11:45 +02:00

424 lines
14 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from functools import total_ordering
from logging import warning as warn
from math import floor
class CalculateError(Exception):
pass
class Fraction(object):
@staticmethod
def log(*args):
if len(args) == 0:
return
line1 = ''
line2 = ''
line3 = ''
for msg in args:
if isinstance(msg, Fraction):
temp = (len(str(max(msg._numerator, msg.denominator)))) // 2 + 1
line1 += ' ' * temp
line1 += str(msg._numerator) + ' ' * temp
line3 += ' ' * temp
line3 += str(msg.denominator) + ' ' * temp
line2 += ' ' * temp + '' * temp + ' '
else:
line1 += ' ' * len(str(msg))
line3 += ' ' * len(str(msg))
line2 += str(msg)
if line1.strip() != '':
print(line1)
print(line2)
if line3.strip() != '':
print(line3)
def __gongyue(self, a, b):
a, aa, b, bb = abs(a), a / abs(a), abs(b), b / abs(b)
while b != 0:
temp = a % b
a = b
b = temp
return a * aa * bb
def __init__(self, _numerator, denominator):
if denominator == 0:
raise CalculateError("fatal error:Denominator = 0")
self._numerator = _numerator
self.denominator = denominator
# 只有满足交换律的才能使用self.__r..__ = self.__..__
def __float__(self):
temp = self._numerator / self.denominator
if not isinstance(temp, float):
temp = float(temp)
return temp
def __int__(self):
return int(float(self))
def general(self, factor):
self._numerator *= factor
self.denominator *= factor
def isSimple(self):
return self.__gongyue(self.numerator, self.denominator) == 1
def all(self):
return self._numerator, self.denominator
def reduction(self, factor=None):
if factor is None:
factor = self.__gongyue(self._numerator, self.denominator)
if self._numerator / factor != floor(self._numerator / factor) or self.denominator / factor != floor(
self.denominator / factor):
warn(f"Reduction failed.Cannot reduction by {factor}")
return
self._numerator //= factor
self.denominator //= factor
def common(self, other):
if type(other) != int and (not isinstance(other, Fraction)) and type(other) != float:
raise TypeError(
f"can only concatenate Fraction (not {type(other)}) to Fraction")
else:
if isinstance(other, float):
ofra = VulgarFraction(
self.denominator * other, self.denominator)
elif isinstance(other, float):
l = 10 ** len(str(other).split(".")[1])
ofra = VulgarFraction(int(other * l), l)
ofra.reduction()
p = ofra.denominator * \
self.denominator // self.__gongyue(
ofra.denominator, self.denominator)
self._numerator *= p // self.denominator
ofra._numerator *= p // ofra.denominator
self.denominator, ofra.denominator = p, p
else:
if isinstance(other, MixedFraction):
ofra = other.toVulgar()
else:
ofra = VulgarFraction(other._numerator, other.denominator)
p = ofra.denominator * \
self.denominator // self.__gongyue(
ofra.denominator, self.denominator)
self._numerator *= p // self.denominator
ofra._numerator *= p // ofra.denominator
self.denominator, ofra.denominator = p, p
return ofra
@total_ordering
class VulgarFraction(Fraction):
def __init__(self, numerator, denominator):
super().__init__(numerator, denominator)
self.numerator = numerator
self.denominator = denominator
self.__radd__ = self.__add__
self.__rmul__ = self.__mul__
def toMixed(self):
temp = MixedFraction(0, 0, self.denominator)
temp.numerator = self.numerator
return temp
@property
def numerator(self):
return self._numerator
@numerator.setter
def numerator(self, value):
self._numerator = value
def __repr__(self):
if self.numerator == self.denominator:
return '1'
if self.numerator == 0:
return '0'
if self.denominator == 1:
return str(self.numerator)
return f" {self.numerator}\n{('' * (len(str(max(self.numerator, self.denominator))) + 2))}\n {self.denominator}"
def __pos__(self):
return self
def __neg__(self):
return VulgarFraction(-self.numerator, self.denominator)
def __add__(self, other):
if type(other) == MixedFraction:
other = MixedFraction(
other.integer, other.numerator, other.denominator).toVulgar()
fra = VulgarFraction(self.numerator, self.denominator)
if type(other) == int:
fra.numerator += other * fra.denominator
elif type(other) == float or isinstance(other, Fraction):
temp = fra.common(other).numerator
fra.numerator += temp
else:
raise TypeError(
f"can only concatenate Fraction (not {type(other)}) to Fraction")
fra.reduction()
return fra
def __sub__(self, other):
if type(other) == MixedFraction:
other = MixedFraction(
other.integer, other.numerator, other.denominator).toVulgar()
fra = VulgarFraction(self.numerator, self.denominator)
if type(other) == int:
fra.numerator -= other * fra.denominator
elif type(other) == float or isinstance(other, Fraction):
temp = fra.common(other).numerator
fra.numerator -= temp
else:
raise TypeError(
f"can only concatenate Fraction (not {type(other)}) to Fraction")
fra.reduction()
return fra
def __rsub__(self, other):
return -(self - other)
def __rtruediv__(self, other):
return (self / other).rec()
def __mul__(self, other):
if type(other) == MixedFraction:
other = MixedFraction(
other.integer, other.numerator, other.denominator).toVulgar()
fra = VulgarFraction(self.numerator, self.denominator)
if type(other) == int:
fra.numerator *= other
elif type(other) == float or isinstance(other, Fraction):
temp = fra.common(other)
fra.numerator *= temp.numerator
fra.denominator *= temp.denominator
else:
raise TypeError(
f"can only concatenate Fraction (not {type(other)}) to Fraction")
fra.reduction()
return fra
def __truediv__(self, other):
if type(other) == MixedFraction:
other = MixedFraction(
other.integer, other.numerator, other.denominator).toVulgar()
fra = VulgarFraction(self.numerator, self.denominator)
if type(other) == int:
fra.denominator *= other
elif type(other) == float or isinstance(other, Fraction):
temp = fra.common(other)
fra.numerator *= temp.denominator
fra.denominator *= temp.numerator
else:
raise TypeError(
f"can only concatenate Fraction (not {type(other)}) to Fraction")
fra.reduction()
return fra
def __eq__(self, other):
fra = VulgarFraction(self.numerator, self.denominator)
if type(other) == MixedFraction:
otr = other.toVulgar()
otr = fra.common(otr)
else:
otr = fra.common(other)
return fra.numerator == otr.numerator
def __lt__(self, other):
fra = VulgarFraction(self.numerator, self.denominator)
if type(other) == MixedFraction:
otr = other.toVulgar()
otr = fra.common(otr)
else:
otr = fra.common(other)
return fra.numerator < otr.numerator
def irec(self): # 你这个是直接赋值return的是None啊
self.numerator, self.denominator = self.denominator, self.numerator
def rec(self): # 有返回值的倒数
return VulgarFraction(self.denominator, self.numerator)
def __pow__(self, other):
if isinstance(other, (VulgarFraction, int, float)):
return VulgarFraction(self.numerator ** float(other), self.denominator ** float(other))
elif isinstance(other, MixedFraction):
return self ** other.toVulgar()
else:
raise CalculateError
def __mod__(self, other):
otr = self.common(other)
return VulgarFraction((self.numerator % otr.numerator), otr.denominator)
def __floordiv__(self, other):
return (self / other).__int__()
def __abs__(self):
return VulgarFraction(abs(self.numerator), abs(self.denominator))
def __call__(self, numerator, denominator, *args):
if args:
raise CalculateError("only 2 arguments")
self.denominator = denominator
self.numerator = numerator
def __complex__(self):
return eval(f"{self.numerator}+{self.denominator}i")
def __format__(self, format_spec):
format_spec = int(format_spec)
if format_spec == 0:
return str(self)
elif format_spec == 1:
return f"{self.numerator}/{self.denominator}"
elif format_spec == 2:
return f"{self.numerator}÷{self.denominator}"
@total_ordering
class MixedFraction(Fraction):
def __init__(self, integer, numerator, denominator):
if int(integer) != integer:
raise CalculateError("integer should be int(or int-like float)")
if numerator >= denominator:
raise CalculateError(
"Numerator should be smaller than denominator")
if integer < 0:
raise CalculateError(
"fatal error:Calculate failed.Cause integer < 0")
super().__init__(numerator, denominator)
self.integer = integer
self.__radd__ = self.__add__
self.__rmul__ = self.__mul__
def __eq__(self, other):
fra = MixedFraction(self.integer, self.numerator,
self.denominator).toVulgar()
otr = fra.common(other)
return fra == otr
def __lt__(self, other):
fra = MixedFraction(self.integer, self.numerator,
self.denominator).toVulgar()
otr = fra.common(other)
return fra < otr
def toVulgar(self):
num = self.integer * self.denominator + self.numerator
f = VulgarFraction(num, self.denominator)
return f
def all(self):
return (self.integer, self.numerator, self.denominator)
def irec(self):
fra = MixedFraction(self.integer, self.numerator,
self.denominator).toVulgar()
fra.irec()
self.integer = 0
self.denominator = fra.denominator
self.numerator = fra.numerator
def rec(self):
temp = self
temp.irec()
return temp
@property
def numerator(self):
return self._numerator
def __mod__(self, other):
return float(self) % float(other)
@numerator.setter
def numerator(self, value):
nm = value
def itg():
nonlocal self
nonlocal nm
temp = nm // self.denominator
if temp > 0:
nm -= self.denominator * temp
self.integer += temp
if nm >= self.denominator:
itg()
elif nm < 0:
nm += self.integer * self.denominator
self.integer = 0
itg()
else:
pass
self._numerator = nm
self.reduction()
def __str__(self):
if self.numerator == 0:
return str(self.integer)
return f"{' ' * len(str(self.integer)) if self.integer != 0 else ''}{self.numerator}\n{self.integer if self.integer != 0 else ''}{'' * len(str(max(self.numerator, self.denominator)))}\n{' ' * len(str(self.integer)) if self.integer != 0 else ''}{self.denominator}"
def __add__(self, other):
fra = MixedFraction(self.integer, self.numerator,
self.denominator).toVulgar()
return (fra + other).toMixed()
def __sub__(self, other):
fra = MixedFraction(self.integer, self.numerator,
self.denominator).toVulgar()
return (fra - other).toMixed()
def __mul__(self, other):
fra = MixedFraction(self.integer, self.numerator,
self.denominator).toVulgar()
return (fra * other).toMixed()
def __truediv__(self, other):
fra = MixedFraction(self.integer, self.numerator,
self.denominator).toVulgar()
return (fra / other).toMixed()
def __rsub__(self, other):
return -(self - other)
def __rtruediv__(self, other):
return (self / other).rec()
def __call__(self, integer, numerator, denominator, *args):
if args:
raise CalculateError('only 3 arguments')
self.integer = integer
self.denominator = denominator
self.numerator = numerator
class ComplexFraction(Fraction):
def __init__(self, numerator: complex, denominator: complex):
super().__init__(numerator, denominator)
self.numerator = numerator
self.denominator = denominator
def common(self, other):
def is_int(number):
return abs(number-round(number)) == 0
def complex_to_complex_fraction(number):
pass # 没做完
def is_complex_int(number:complex):
return is_int(number.imag) and is_int(number.real)
if __name__ == "__main__":
a = VulgarFraction(10, 20)
print(
format(a, "1")
)