我目前正在实施Fraction
class
来培训我的OOP技能,而且我遇到了一个问题...在我的课堂上,你可以在math
之间进行Fraction
次操作:
我想添加两个:
因为当我使用整数时,我所做的就是将它们设为float
,分母为1,我希望在使用Fraction
进行操作时,创建代表该float
的{{1}}给定Fraction
。这就是我遇到问题的地方。
首先,了解我的class
class Fraction(object):
def __init__(self,num,den=1,reduce=True):
# only accept integers or convertable strings
if not(type(num) == int and type(den) == int):
if type(num) == str:
try:
num = int(num)
except ValueError:
raise RuntimeError("You can only pass to the numerator and \
denominator integers or integer convertable strings!")
else:
raise RuntimeError("You can only pass to the numerator and \
denominator integers or integer convertable strings!")
if type(den) == str:
try:
den = int(den)
except ValueError:
raise RuntimeError("You can only pass to the numerator and \
denominator integers or integer convertable strings!")
else:
raise RuntimeError("You can only pass to the numerator and \
denominator integers or integer convertable strings!")
# don't accept fractions with denominator 0
if den == 0:
raise ZeroDivisionError("The denominator must not be 0")
# if both num and den are negative, flip both
if num < 0 and den < 0:
num = abs(num)
den = abs(num)
# if only the den is negative, change the "-" to the numerator
elif den < 0:
num *= -1
den = abs(den)
self.num = num
self.den = den
# the self.auto is a variable that will tell us if we are supposed to
#automatically reduce the Fraction to its lower terms. when doing some
#maths, if either one of the fractions has self.auto==False, the result
#will also have self.auto==False
self.auto = reduce
if self.auto:
self.reduce()
def float_to_fraction(f):
'''should not be called by an instance of a Fraction, since it does not\
accept, purposedly, the "self" argument. Instead, call it as\
Fraction.float_to_fraction to create a new Fraction with a given float'''
# Start by making the number a string
f = str(f)
exp = ""
# If the number has an exponent (is multiplied by 10 to the power of sth
#store it for later.
if "e" in f:
# Get the "e+N" or "e-N"
exp = f[f.index("e"):]
# Slice the exponent from the string
f = f[:f.index("e")]
# Start the numerator and the denominator
num = "0"
den = "1"
# Variable to check if we passed a ".", marking the decimal part of a
#number
decimal = False
for char in f:
if char != ".":
# Add the current char to the numerator
num += char
if decimal:
# If we are to the right of the ".", also add a 0 to the
#denominator to keep proportion
den += "0"
# Slice parsed character
f = f[1:]
if char == ".":
# Tell the function we are now going to the decimal part of the
#float.
decimal = True
# Slice the "."
f = f[1:]
# Parse the exponent, if there is one
if exp != "":
# If it is a negative exponent, we should make the denominator bigger
if exp[1] == "-":
# Add as many 0s to the den as the absolute value of what is to
#the right of the "-" sign. e.g.: if exp = "e-12", add 12 zeros
den += "0"*int(exp[2:])
# Same stuff as above, but in the numerator
if exp[1] == "+":
num += "0"*int(exp[2:])
# Last, return the Fraction object with the parsed num and den!
return Fraction(int(num),int(den))
:
float_to_fraction()
我的float
功能可以100%准确地将给定的Fraction
转换为0.123123123123
。但是,正如我从数学课中记得的那样,一个带有n位长周期的循环小数,如0.(123)
...或numerator = cycle
,可以用denominator = (as many 9s as the length of the cycle)
的分数形式写出来123/999 = 0.(123)
:
3/9 (=1/3) = 0.(3); 142857/999999 (=1/7) = 0.(142857)
float_to_fraction()
等等......
但是通过这个实现,如果我传递给3333333333333333/10000000000000000
一个像1/3这样的参数,它将解析有限的“0.3333333333333333”,返回此分数:Fraction
。它是准确的,因为我传递给函数有限数!如何在此函数中实现一种识别循环小数的方法,因此我可以返回带有denominator = 10^n
的{{1}},而不是带有9的负载的分母。
答案 0 :(得分:0)
将十进制表达式转换为近似理性的最佳方法是通过连续的分数扩展。
对于x = 0.123123123123,这导致
r=x,
a[0]=floor(r)=0, r=r-a[0], r=1/r=8.121951219520,
a[1]=floor(r)=8, r=r-a[1], r=1/r=8.199999999453,
a[2]=floor(r)=8, r=r-a[2], r=1/r=5.000000013653,
a[3]=floor(r)=5, r=r-a[3], r=1/r=73243975.48780,
此时r-a[3]<1e-5
迭代停止。找到的有理逼近是
x=1/(8+1/(8+1/5))=1/(8+5/41)=41/333 (=123/999)
中间收敛是
1/8=0.125, x- 1/8 = -0.001876876877,
1/(8+1/8)=8/65, x- 8/65 = 0.0000462000460,
41/333, x-41/333 = -1.231231231231e-13.