Last active
July 3, 2020 05:15
-
-
Save LiuQixuan/77ff903bd48ddd9a534fe627e6eb337f to your computer and use it in GitHub Desktop.
支持四则运算的分数类
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
##! %Python_Home%/python3 | |
#-*- coding:utf-8 -*- | |
#@Time: 2020-07-01 | |
#@Author: LiuQixuan | |
#@Email: [email protected] | |
#@File: Fraction.py | |
#@Description: Fraction 类为一个支持四则运算的分数类,构造函数接受可变长参数.表示为"分子/分母",仅支持真分 | |
# 数假分数表示,不支持带分数表示. | |
# 参数说明:构造函数可接受单个字符型参数或多个整数浮点字符混合参数,但是最终处理参数不多于一个.无参数时 | |
# 返回自然数1的分数形式.构造参数一般形态{4/5},接受浮点型{5/1.2},{3.4/1.3}, {2.7/3}等出现浮点型时自动 | |
# 转化为"分子/分母"表示形式.构造函数接受字符型{"1.2/5"},{"2/7"},{"1.2"},{"3"},最终,全部转化 | |
# 为"分子/分母"形式. | |
# 特殊情况:{0}或{"0"},结果为0/1.{number/0}结果是nan / nan并抛出分母不能为零异常. | |
# 静态函数:类提供一般的获取分子(numerator),分母(denominator)的接口,可直接修改就像使用一般静态变量一 | |
# 样,实际上是用装饰器实现的,例如:frac.denominator = 123,print(frac.denominator).类还提 | |
# 供getSimplifyFrac方法用于处理认为赋值导致结果未统分的分数. | |
# 输出方式:可直接使用print(frac)进行输出,也可以使用类自带的输出方法输出frac.print()使用toFloat方法返 | |
# 回Float类型的分数浮点值. | |
# 说明:最终结果皆是统分后的最简结果. | |
# | |
from math import floor | |
class Fraction(): | |
def __init__(self,*args): | |
# print('[Info] Args:',args) | |
# print('[Info] Args.length:',len(args)) | |
numerator,denominator = [1,1] | |
if(args == ()): | |
numerator,denominator = [1,1] | |
elif(isinstance(args[0],str)): | |
numerator,denominator = self.__byString(args[0]) | |
elif(len(args)==1): | |
if(isinstance(args[0],int)): | |
numerator,denominator = [args[0],1] | |
elif(isinstance(args[0],float)): | |
numerator,denominator = self.__byFloat(args[0]) | |
else: | |
if(args[1] == 0 or args[1]=='0'): | |
try: | |
raise Exception('[ERRO] Exception: parameter error: the denominator cannot be zero') | |
except Exception as e: | |
print(e.args[0]) | |
finally: | |
numerator,denominator = [float('nan'),float('nan')] | |
elif(args[0] == 0): | |
numerator,denominator = [0,1] | |
elif(isinstance(args[0],int) and isinstance(args[1],int)): | |
numerator,denominator = [args[0],args[1]] | |
else: | |
frac = Fraction(args[0])/Fraction(args[1]) | |
numerator,denominator = [frac.numerator,frac.denominator] | |
self._numerator = numerator | |
self._denominator = denominator | |
# print(f'[Success] Fraction: build success.',f"{self._numerator}/{self._denominator}") | |
@property | |
def numerator(self): | |
return self._numerator | |
@property | |
def denominator(self): | |
return self._denominator | |
@numerator.setter | |
def numerator(self,v): | |
self._numerator = v | |
@denominator.setter | |
def denominator(self,v): | |
self._denominator = v | |
def __byString(self,str): | |
numerator,denominator = [1,1] | |
if(str.find('/')==-1): | |
numerator,denominator = self.__byFloat(float(str)) | |
else: | |
argArr = str.split('/',1) | |
if (argArr[1] == '0'): | |
try: | |
raise Exception('[ERRO] Exception: parameter error: the denominator cannot be zero') | |
except Exception as e: | |
print(e.args[0]) | |
finally: | |
numerator,denominator = [float('nan'),float('nan')] | |
else: | |
frac = Fraction(argArr[0])/Fraction(argArr[1]) | |
numerator,denominator = [frac.numerator,frac.denominator] | |
return [numerator,denominator] | |
def __byFloat(self,v_f): | |
lenOfDeno = len(str(v_f).split('.')[1]) | |
denominator = lenOfDeno*10 | |
numerator = v_f*denominator | |
numerator,denominator = self.__simplifyFrac(numerator,denominator) | |
return [numerator,denominator] | |
@staticmethod | |
def _isFloat(v): | |
return v-floor(v)>0 | |
def __repr__(self): | |
return f"{self._numerator}/{self._denominator}" | |
def toFloat(self): | |
return self.numerator/self.denominator | |
@classmethod | |
def __simplifyFrac(cls,numerator,denominator): | |
if(denominator==0): | |
numerator,denominator = [1,0] | |
else: | |
gcd = cls.__gcd(denominator,numerator) | |
numerator,denominator = [int(numerator/gcd),int(denominator/gcd)] | |
return [numerator,denominator] | |
@staticmethod | |
def getSimplifyFrac(frac): | |
return Fraction(*Fraction.__simplifyFrac(frac.numerator,frac.denominator)) | |
@staticmethod | |
def __gcd(a,b): | |
t = 0 | |
while(b!=0): | |
t,a = a%b,b | |
b = t | |
return a | |
def print(self): | |
print(self._numerator,self._denominator,sep = '\n----\n',end = '\n\n') | |
# 加减乘除 | |
def __add__(self,other): | |
gcd = self.__gcd(self._denominator,other._denominator) | |
denominator = (self._denominator*other._denominator)/gcd | |
numerator = denominator/self._denominator*self._numerator+denominator/other._denominator*other._numerator | |
numerator,denominator = self.__simplifyFrac(numerator,denominator) | |
return Fraction(numerator,denominator) | |
def __sub__(self,other): | |
gcd = self.__gcd(self._denominator,other._denominator) | |
denominator = (self._denominator*other._denominator)/gcd | |
numerator = denominator/self._denominator*self._numerator-denominator/other._denominator*other._numerator | |
numerator,denominator = self.__simplifyFrac(numerator,denominator) | |
return Fraction(numerator,denominator) | |
def __mul__(self,other): | |
numerator = self._numerator*other._numerator | |
denominator = self._denominator*other._denominator | |
numerator,denominator = self.__simplifyFrac(numerator,denominator) | |
return Fraction(numerator,denominator) | |
def __truediv__(self,other): | |
# print(f'[Info] self:{self.__repr__}') | |
# print(f'[Info] other:{other.__repr__}') | |
numerator = self._numerator*other._denominator | |
denominator = self._denominator*other._numerator | |
numerator,denominator = self.__simplifyFrac(numerator,denominator) | |
return Fraction(numerator,denominator) | |
def main(): | |
frac1 = Fraction(4,5) | |
frac2 = Fraction(2,3.1) | |
frac3 = Fraction(1.2,3) | |
frac4 = Fraction('2.3/2') | |
for i in range(1,5): | |
eval(f'frac{i}.print()') | |
frac5 = Fraction('0/0') | |
frac5.print() | |
frac3.numerator = 60 | |
frac3.print() | |
Fraction.getSimplifyFrac(frac3).print() | |
print(frac3) | |
frac6 = Fraction(1,0) | |
frac6.print() | |
print(frac2.toFloat()) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment