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.
For example,
- Given numerator = 1, denominator = 2, return "0.5".
- Given numerator = 2, denominator = 1, return "2".
- Given numerator = 2, denominator = 3, return "0.(6)".
基本思想是用hash table保存余数来检查是否出现循环重复小数。需要注意的地方很多:
1. 需要先转换成long long再取绝对值,否则可能导致溢出。
2. 调试的时候总是遇到unary minus applied to unsigned type, result still unsigned. Why? 原来对于常量-2147483648,编译器首先把它解析成2147483648,然后在此之上执行一元‘-’运算符。由于2147483648对于32位系统会溢出,所以编译器把它看做无符号整形。那么问题来了,编译错误。怎么办呢?可以用long long,或者numeric_limits<int>::min()来取得-2147483648。也就是说呢,没有负的字面量,negative literal,编译器用正的字面量和unary minus来表示。
3. 分数总能转换成小数?记得是这样,网上貌似也是这样说,国内的国外的。那么1/2147483647,我怎么运算到字符串都1M了还结束不了???
class Solution {
public:
string fractionToDecimal(int numerator, int denominator) {
bool positive = true;
if (((numerator & 0x80000000) ^ (denominator & 0x80000000)) != 0) {
positive = false;
}
long long abs_numerator = abs(static_cast<long long>(numerator));
long long abs_denominator = abs(static_cast<long long>(denominator));
string result;
long long quotient = abs_numerator / abs_denominator;
while (quotient != 0) {
int lsdigit = quotient % 10;
result.push_back(static_cast<char>(lsdigit + '0'));
quotient /= 10;
}
if (!result.empty()) {
reverse(result.begin(), result.end());
}
else {
result.push_back('0');
}
if (!positive && abs_numerator != 0) {
result.insert(result.begin(), '-');
}
long long remainder = abs_numerator % abs_denominator;
if (remainder == 0) {
return result;
}
result.push_back('.');
unordered_map<long long, size_t> remainders;
while (remainder != 0) {
remainder *= 10;
auto repeat = remainders.find(remainder);
if (repeat != remainders.end()) {
result.insert(repeat->second, 1, '(');
result.push_back(')');
break;
}
int msdigit = remainder / abs_denominator;
result.push_back(static_cast<char>(msdigit + '0'));
remainders[remainder] = result.size() - 1;
remainder %= abs_denominator;
}
return result;
}
};