Skip to content

Instantly share code, notes, and snippets.

@LiuQixuan
Last active July 3, 2020 05:15
Show Gist options
  • Save LiuQixuan/77ff903bd48ddd9a534fe627e6eb337f to your computer and use it in GitHub Desktop.
Save LiuQixuan/77ff903bd48ddd9a534fe627e6eb337f to your computer and use it in GitHub Desktop.
支持四则运算的分数类
##! %Python_Home%/python3
#-*- coding:utf-8 -*-
#@Time: 2020-07-01
#@Author: LiuQixuan
#@Email: liuqixuan@hotmail.com
#@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