力扣第166题-分数到小数

225 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第27天,点击查看活动详情

前言

力扣第166题 分数到小数 如下所示:

image.png

一、思路

题目意思很简单,就是输入一个小数(分子 + 分母的形式),输出计算后的小数。有如下的三种情况:

  1. 正好整除,则返回一个整数。例如 4 / 2 = 2
  2. 可以除尽的有限小数。如 3 / 2 = 1.5
  3. 除不尽的无线循环小数。如 1 / 3 = 0.(3)

一二两种情况都很好处理,只需要简单的使用除法即可。如何通过计算知道一个分数是无线循环小数呢?在这里我们先以示例中的 4 / 333 为例子分析,模拟计算的步骤人如下所示:

ret:表示小数结果

  1. 因为 4 < 333,先将分子扩大 100 倍,即 400 / 333(后面再除 100
  2. 400 / 333 = 1...67,余数为 67。此时 ret = 0.01
  3. 670 / 333 = 2...4,余数为 4。此时 ret = 0.012
  4. 40 < 333,故上零。此时 ret = 0.0120
  5. 400 / 333 = 1...67,余数为 67。此时 ret = 0.01201

我们发现在第五步中的 除数被除数400/333 在前面的步骤中是出现过的,也就是说这个小数是无限循环小数。但是实际上第四步中的 40 / 333 已经出现过了,也就是说循环的部分为 012,即小数为 0.(012)

综上所述,我们在处理的过程模拟以上的过程即可。大致分为以下几步:

  1. 如过可以整除,则返回结果即可
  2. 使用 哈希表 存储小数计算过程中的 被除数,如果出现了相同的被除数说明出现了循环。返回正确的小数字符串即可

二、实现

实现代码

public String fractionToDecimal(int numerator, int denominator) {
    long divisor = numerator;   // 被除数
    long dividend = denominator;    // 除数
    // 整数
    if (divisor % dividend == 0) {
        return String.valueOf(divisor / dividend);
    }
    StringBuilder sb = new StringBuilder();
    if (divisor * dividend < 0) {
        sb.append('-');
    }

    divisor = Math.abs(divisor);
    dividend = Math.abs(dividend);
    // 整数部分
    sb.append(divisor / dividend).append('.');
    // 小数部分
    StringBuilder decimal = new StringBuilder();
    Map<Long, Integer> map = new HashMap<>();   // 存储被除数
    long remainder = divisor % dividend;
    int index = 0;
    while (remainder != 0 && !map.containsKey(remainder)) {
        map.put(remainder, index);
        remainder *= 10;
        decimal.append(remainder / dividend);
        remainder = remainder % dividend ;
        index++;
    }
    if (remainder != 0) { // 有循环节
        int p = map.get(remainder);
        decimal.insert(p, '(');
        decimal.append(')');
    }
    sb.append(decimal);
    return sb.toString();
}

测试代码

public static void main(String[] args) {
    new Number166().fractionToDecimal(4, 333);
}

结果

image.png

三、总结

感谢看到最后,非常荣幸能够帮助到你~♥

如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~