原题链接:https://leetcode-cn.com/problems/fraction-to-recurring-decimal/。
简述题目的要求:将一个分数表示成小数,而且将循环节部分用括号括起来。
解题思路:
求这个小数的整数部分比较简单。
求小数部分:求小数的每一位,要将上一步求得余数乘以10得到下一步的除数。则这一位的数字就是除数除以被除数的商。
关于无限循环小数:建立一个map,键值对存储的是:key:每一步的除数,value:小数的每一位数索引。
-
例如对于一个分数计算求小数部分:
计算1/6的小数。小数的第0索引为应该由 1*10//6计算得到1,余数为4.此时map添加一个键值对<10,0>。
小数的第1索引应该由 4 * 10 // 6计算的到6,余数为4.此时map添加一个键值对<40,1>。
小数的第2索引本应该由 4 * 10 // 6计算。添加键值对 <40,2>。可见40已经存在于map中。说明已经有循环部分而且循环的部分应该在[map[40],2)。(包括前不包括后)
下面是python3程序。 -
对于分子分母有负数的情况:
先计算绝对值,如果负数的个数只有一个,在最后输出的字符串添加一个‘-’。
class Solution:
def fractionToDecimal(self, numerator, denominator):
"""
:type numerator: int
:type denominator: int
:rtype: str
"""
if numerator == 0:
return '0'
zhengfuflag = False
if (numerator <0 and denominator >=0) or (numerator >=0 and denominator <0):
zhengfuflag = True
# 计算绝对值
numerator = abs(numerator)
denominator = abs(denominator)
# 计算整数部分
remainder = numerator % denominator
quotient = numerator // denominator
if remainder != 0:
qutientstr = ''
numeratormap = dict()
remainder *= 10
i = 0
j = 0
numeratormap[remainder] = 0
flag = True
while True:
i += 1
thisremainder = remainder % denominator
thisquotient = remainder // denominator # 计算小数这一位的值
remainder = thisremainder * 10 # 得到下一步的除数
if thisremainder == 0 and thisquotient == 0:
flag = False
break
if remainder not in numeratormap: # 判断下一步的除数是否已经在map中
numeratormap[remainder] = i # 如果不在将其加入map中,继续循环
qutientstr += str(thisquotient)
else:
j = numeratormap[remainder] # 如果除数已经在map中。输出同样除数上一次出现的索引
qutientstr += str(thisquotient)
break
if flag:
qutientstr = qutientstr[0:j] + '(' + qutientstr[j:] # 在指定位置加入括号
qutientstr += ')'
res = str(quotient)+'.'+qutientstr
return '-'+ res if zhengfuflag else res # 判断结果是否为负加入符号
else:
return '-' + str(quotient) if zhengfuflag else str(quotient)