class Solution:
def fractionToDecimal(self, numerator: int, denominator: int) -> str:
if numerator == 0:
return "0"
res = []
# Determine the sign
if (numerator < 0) != (denominator < 0):
res.append('-')
numerator, denominator = abs(numerator), abs(denominator)
# Integer part
res.append(str(numerator // denominator))
remainder = numerator % denominator
if remainder == 0:
return ''.join(res)
res.append('.')
# Fractional part
rem_pos = {}
while remainder:
if remainder in rem_pos:
res.insert(rem_pos[remainder], '(')
res.append(')')
break
rem_pos[remainder] = len(res)
remainder *= 10
res.append(str(remainder // denominator))
remainder %= denominator
return ''.join(res)
class Solution {
public:
string fractionToDecimal(int numerator, int denominator) {
if (numerator == 0) return "0";
string res;
// Sign
if ((numerator < 0) ^ (denominator < 0)) res += "-";
long num = labs(numerator);
long den = labs(denominator);
// Integer part
res += to_string(num / den);
long rem = num % den;
if (rem == 0) return res;
res += ".";
unordered_map<long, int> rem_pos;
while (rem) {
if (rem_pos.count(rem)) {
res.insert(rem_pos[rem], 1, '(');
res += ")";
break;
}
rem_pos[rem] = res.size();
rem *= 10;
res += to_string(rem / den);
rem %= den;
}
return res;
}
};
class Solution {
public String fractionToDecimal(int numerator, int denominator) {
if (numerator == 0) return "0";
StringBuilder res = new StringBuilder();
// Sign
if ((numerator < 0) ^ (denominator < 0)) res.append("-");
long num = Math.abs((long) numerator);
long den = Math.abs((long) denominator);
// Integer part
res.append(num / den);
long rem = num % den;
if (rem == 0) return res.toString();
res.append(".");
Map<Long, Integer> remPos = new HashMap<>();
while (rem != 0) {
if (remPos.containsKey(rem)) {
res.insert(remPos.get(rem), "(");
res.append(")");
break;
}
remPos.put(rem, res.length());
rem *= 10;
res.append(rem / den);
rem %= den;
}
return res.toString();
}
}
var fractionToDecimal = function(numerator, denominator) {
if (numerator === 0) return "0";
let res = '';
// Sign
if ((numerator < 0) !== (denominator < 0)) res += '-';
let num = Math.abs(numerator);
let den = Math.abs(denominator);
// Integer part
res += Math.floor(num / den);
let rem = num % den;
if (rem === 0) return res;
res += '.';
let remPos = {};
while (rem) {
if (rem in remPos) {
res = res.slice(0, remPos[rem]) + '(' + res.slice(remPos[rem]) + ')';
break;
}
remPos[rem] = res.length;
rem *= 10;
res += Math.floor(rem / den);
rem %= den;
}
return res;
};
Given two integers, numerator
and denominator
, return the fraction as a string in decimal form. If the fractional part is repeating, enclose the repeating part in parentheses.
Key constraints:
numerator
and denominator
can be negative or zero.numerator = 1, denominator = 2
→ "0.5"
numerator = 2, denominator = 3
→ "0.(6)"
numerator = 4, denominator = 333
→ "0.(012)"
To solve this problem, we need to simulate division and keep track of repeating decimals. At first, you might think of simply dividing numerator
by denominator
using floating-point arithmetic, but this will not handle repeating decimals or the requirement to enclose repeated parts in parentheses.
The key insight is that repeating decimals occur when the same remainder appears again during the division process. By tracking remainders and their positions in the result, we can detect the start of a repeating sequence. This is similar to how you would perform long division by hand, writing down each step and noticing when a remainder repeats.
We also need to handle edge cases such as negative numbers, zero, and when the division results in no fractional part.
We can break the solution down into the following steps:
numerator
is zero, the result is simply "0".
numerator
or denominator
is negative. We append a '-' sign if necessary.
numerator
by denominator
to get the integer part. Append this to the result.
denominator
to get each digit after the decimal point.The use of a hash map (dictionary) for remainder positions is crucial because it allows us to detect repeating cycles in O(1) time per digit, making the solution efficient.
Let's walk through the example numerator = 2, denominator = 3
:
2 / 3 = 0
. So, result so far is "0".2 % 3 = 2
. Start the fractional part, add '.'.2 * 10 = 20
. 20 / 3 = 6
, so add '6' to result ("0.6"). New remainder: 20 % 3 = 2
.This process ensures that only the repeating part is inside parentheses, and the string representation is correct.
Brute-force Approach:
This approach is efficient and avoids the pitfalls of floating-point arithmetic by simulating the division process manually.
The solution to the "Fraction to Recurring Decimal" problem involves simulating manual division and tracking remainders to detect cycles. By using a hash map to remember where each remainder first appeared, we can efficiently identify repeating decimals and correctly format the result with parentheses. The approach is both accurate and efficient, making it a robust solution for handling all edge cases, including negative numbers and repeating decimal cycles.