Description:
Given two integers representing the numerator and denominator of a fraction, return the fraction in string format.
If the fractional part is repeating, enclose the repeating part in parentheses.
Example 1:
Input: numerator = 1, denominator = 2
Output: "0.5"
Example 2:
Input: numerator = 2, denominator = 1
Output: "2"
Example 3:
Input: numerator = 2, denominator = 3
Output: "0.(6)"
Solution:
NOTE: 各种edge cases,相当恶心。比如Python str(1/2147483648)结果是“0”,因为根本不知道要求是什么(输入分子分母的范围),所以也无法确定应该使用的方法;比如"0.0"不行非要输出"0"。唯一有意思的是对无限循环位数的判断,在slot函数里。digits这个变量表示小数点以后显示多少位,包括不循环和循环的部分。
class Solution:
def fractionToDecimal(self, numerator: int, denominator: int) -> str:
if numerator/denominator == numerator//denominator: # 22/2 => 11 not 11.0
return str(numerator//denominator) # 0/-5 => 0 not 0.0
gcd = math.gcd(numerator,denominator) # 50/8 => 6.25 not 6.250
numerator //= gcd
denominator //= gcd
if denominator == 1: # 2.0 => 2
return str(numerator)
sign = int(numerator*denominator < 0) # -7/12 => -7//12 和 -7%12在Python里都是错的结果
numerator = abs(numerator)
denominator = abs(denominator)
def slot(denominator):
i = 10
cnt = 1
while (i-1)%denominator != 0:
i *= 10
cnt += 1
return cnt
def helper(nume,deno):
two = 0
while deno%2 == 0:
deno //= 2
two += 1
five = 0
while deno%5 == 0:
deno //= 5
five += 1
nume *= pow(10,max(two,five))
nume //= pow(2,two)*pow(5,five)
digits = max(two,five)
if deno != 1:
if digits == 0:
ret = ".("
else:
ret = "." + str(nume//deno).zfill(digits) + "("
nume %= deno
cache = ""
for i in range(slot(deno)):
nume *= 10
cache += str(nume//deno)
nume = nume%deno
if int(cache) == 0:
return ""
else:
return ret + cache + ")"
else:
return "." + str(nume).zfill(digits)
return str(sign*"-") + str(numerator//denominator) + helper(numerator%denominator,denominator)
Runtime: 32 ms, faster than 92.16% of Python3 online submissions for Fraction to Recurring Decimal.
Memory Usage: 13.8 MB, less than 5.95% of Python3 online submissions for Fraction to Recurring Decimal.