返回

算法题解——LeetCode每日一题|166. 分数到小数

前端

对于分数到小数的转换,很多同学第一想到的可能是长除法。虽然长除法是一个直接的方法,但我们也可以用更加巧妙的数学方法来解决这个问题。

思路分析

首先,我们需要检查分子和分母是否有公约数。如果有,那么我们可以先约分,这样可以减少计算量。

接下来,我们需要将分子除以分母,得到一个整数部分和一个余数。整数部分就是小数点前面的部分,余数就是小数点后面的部分。

如果余数为0,那么小数部分就结束了。否则,我们将余数乘以10,然后继续除以分母。这样,我们就可以得到小数部分的下一位数字。

重复这个过程,直到余数为0,或者小数部分达到我们想要的精度。

输出结果

输出结果分为三个部分:符号、整数、小数。

  • 符号:如果分子和分母异号,那么符号为负号;否则,符号为正号。
  • 整数:整数部分就是分子除以分母得到的整数部分。
  • 小数:小数部分就是余数不断除以分母得到的结果。

编程实现

以下是Python、Java、C++、Javascript等多种编程语言的解题代码:

Python代码:

def fractionToDecimal(numerator, denominator):
    """
    :type numerator: int
    :type denominator: int
    :rtype: str
    """
    # 检查分子和分母是否有公约数
    gcd = math.gcd(numerator, denominator)
    if gcd > 1:
        numerator //= gcd
        denominator //= gcd

    # 计算整数部分
    integer_part = numerator // denominator

    # 计算余数
    remainder = numerator % denominator

    # 如果余数为0,那么小数部分就结束了
    if remainder == 0:
        return str(integer_part)

    # 将余数乘以10,然后继续除以分母
    decimal_part = ""
    seen = set()
    while remainder != 0 and remainder not in seen:
        seen.add(remainder)
        remainder *= 10
        digit = remainder // denominator
        remainder %= denominator
        decimal_part += str(digit)

    # 如果小数部分有循环,那么在循环开始的地方添加括号
    if remainder in seen:
        index = decimal_part.index(str(remainder))
        decimal_part = decimal_part[:index] + "(" + decimal_part[index:] + ")"

    # 返回结果
    return str(integer_part) + "." + decimal_part

Java代码:

class Solution {
    public String fractionToDecimal(int numerator, int denominator) {
        // 检查分子和分母是否有公约数
        int gcd = Math.gcd(numerator, denominator);
        if (gcd > 1) {
            numerator /= gcd;
            denominator /= gcd;
        }

        // 计算整数部分
        int integerPart = numerator / denominator;

        // 计算余数
        int remainder = numerator % denominator;

        // 如果余数为0,那么小数部分就结束了
        if (remainder == 0) {
            return String.valueOf(integerPart);
        }

        // 将余数乘以10,然后继续除以分母
        StringBuilder decimalPart = new StringBuilder();
        Set<Integer> seen = new HashSet<>();
        while (remainder != 0 && !seen.contains(remainder)) {
            seen.add(remainder);
            remainder *= 10;
            int digit = remainder / denominator;
            remainder %= denominator;
            decimalPart.append(digit);
        }

        // 如果小数部分有循环,那么在循环开始的地方添加括号
        if (remainder != 0) {
            int index = decimalPart.indexOf(String.valueOf(remainder));
            decimalPart.insert(index, "(");
            decimalPart.append(")");
        }

        // 返回结果
        return integerPart + "." + decimalPart.toString();
    }
}

C++代码:

class Solution {
public:
    string fractionToDecimal(int numerator, int denominator) {
        // 检查分子和分母是否有公约数
        int gcd = std::gcd(numerator, denominator);
        if (gcd > 1) {
            numerator /= gcd;
            denominator /= gcd;
        }

        // 计算整数部分
        int integerPart = numerator / denominator;

        // 计算余数
        int remainder = numerator % denominator;

        // 如果余数为0,那么小数部分就结束了
        if (remainder == 0) {
            return std::to_string(integerPart);
        }

        // 将余数乘以10,然后继续除以分母
        std::string decimalPart;
        std::unordered_set<int> seen;
        while (remainder != 0 && seen.find(remainder) == seen.end()) {
            seen.insert(remainder);
            remainder *= 10;
            int digit = remainder / denominator;
            remainder %= denominator;
            decimalPart += std::to_string(digit);
        }

        // 如果小数部分有循环,那么在循环开始的地方添加括号
        if (remainder != 0) {
            int index = decimalPart.find(std::to_string(remainder));
            decimalPart.insert(index, "(");
            decimalPart += ")";
        }

        // 返回结果
        return std::to_string(integerPart) + "." + decimalPart;
    }
};

Javascript代码:

/**
 * @param {number} numerator
 * @param {number} denominator
 * @return {string}
 */
const fractionToDecimal = (numerator, denominator) => {
    // 检查分子和分母是否有公约数
    const gcd = Math.gcd(numerator, denominator);
    if (gcd > 1) {
        numerator /= gcd;
        denominator /= gcd;
    }

    // 计算整数部分
    const integerPart = Math.floor(numerator / denominator);

    // 计算余数
    let remainder = numerator % denominator;

    // 如果余数为0,那么小数部分就结束了
    if (remainder === 0) {
        return integerPart.toString();
    }

    // 将余数乘以10,然后继续除以分母
    let decimalPart = "";
    const seen = new Set();
    while (remainder !== 0 && !seen.has(remainder)) {
        seen.add(remainder);
        remainder *= 10;
        const digit = Math.floor(remainder / denominator);
        remainder %= denominator;
        decimalPart += digit.toString();
    }

    // 如果小数部分有循环,那么在循环开始的地方添加括号
    if (remainder !== 0) {
        const index = decimalPart.indexOf(remainder.toString());
        decimalPart = decimalPart.substring(0, index) + "(" + decimalPart.substring(index) + ")";
    }

    // 返回结果
    return integerPart + "." + decimalPart;
};

希望本文对您有所帮助。如果您有任何疑问,请随时留言。