题目

题解

这道题其实就是模拟笔算除法的过程,挨个位产生商,主要判断是否除尽或者产生了循环。

class Solution {
public:
    string fractionToDecimal(int numerator, int denominator) {
        string res;
        if(numerator==0) return "0";
        //用异或判断是否为负
        if((numerator<0)^(denominator<0)) res.push_back('-');
        auto n = static_cast<long long>(numerator);
        auto d = static_cast<long long>(denominator);//转为longlong防止溢出
        n = llabs(n);
        d = llabs(d);//取绝对值
        res.append(to_string(n/d));//先添加整数部分

        auto v = n%d;//取余数
        if(v==0) return res;//余数为0,直接返回
        //不为0,继续下面的操作
        res.push_back('.');//在res后加上小数点
        //index存小数点之后的位置,用于map存每个余数的商所在的位置,用于后续在其之前添加'('
        int index = res.size();
        //注意!虽然无限循环小数的商循环,但是有可能出现一个循环内多个相同的数字
        //因此在判断时要判断被除数是否产生了循环,若产生了则证明有循环
        unordered_map<long long, int> m;//map存余数(即被除数)及其下标
        while(v!=0 && m.count(v)==0){//v没别除尽或者没有产生循环
            m[v] = index++;//存当前的余数(即被除数),和其下标,要先存在乘10,否则会死循环
            v *= 10;//余数乘10
            res.append(to_string(v/d));//res加入这个商的整数部分
            v %= d;//v取余
        }
        //跳出while循环说明有循环,找到循环的第一数字,在之前加'(',在res最后加')'
        //注意这里必须加判断,上一步有可能是除尽跳出循环,就不需要加括号
        if(m.count(v)==1){
            res.insert(m[v],"(");
            res.push_back(')');
        }
        return res;
    }