• 【数学】分数到小数 巧用MAP获取循环小数


    题目描述

    给定两整数,分别表示分数的分子(numerator)和分母(denominator),请使用字符串形式返回小数。

    如果小数为循环小数,则将循环的部分括在括号里面。对应给定的输入,保证答案字符串长度小于10000;

    示例1:

    输入:numerator = 4, denominator = 333
    输出:"0.(012)"

    解题思路 

    这道题是:求小数(余数+求商)+找到循环小数。


    对于求小数(余数+求商), 有以下操作流程:

    1. 使用numerator/denominator获得value,这个value就是每一位的小数值;
    2. 使用numerator%denominator获得mod,再将mod * 10 就是下一位要做计算的 numerator;
    3. 最后循环1和2操作就能计算出小数结果。

    对于找到循环小数,有以下操作流程:

    1. 初始化一个modMap,用于记录取模计算mod对应的字符串位置;
    2. 循环代码,判断modMap中是否存在mod如果存在则直接跳出循环;
    3. 使用numerator%denominator获得mod,设置modMap。

    最后是对结果的组装,如果有循环小数则需要组装循环小数,如果没有则直接返回结果。这里组装循环小数是使用了StringBuilder.insert()函数,避免拷贝数据带来的性能损耗。

    代码实现

    1. import java.util.HashMap;
    2. import java.util.Map;
    3. class Solution {
    4. public String fractionToDecimal(int numerator, int denominator) {
    5. // 类型强转,避免溢出
    6. return fractionToDecimal((long) numerator, (long) denominator);
    7. }
    8. public String fractionToDecimal(long numerator, long denominator) {
    9. // 数据预先处理,先获得整数部分,并且确定符号类型
    10. long v = numerator / denominator;
    11. StringBuilder sb = new StringBuilder(10);
    12. if (v == 0) {
    13. if (numerator > 0 && denominator < 0 || numerator < 0 && denominator > 0) {
    14. sb.append("-");
    15. }
    16. sb.append('0');
    17. } else {
    18. sb.append(v);
    19. }
    20. numerator = Math.abs(numerator % denominator);
    21. if (numerator != 0) {
    22. sb.append(".");
    23. }
    24. denominator = Math.abs(denominator);
    25. int start = sb.length();
    26. // 创建modMap记录每个mod的位置
    27. Map modMap = new HashMap<>();
    28. while (numerator != 0 && modMap.get(numerator) == null) {
    29. //记录每个mod的位置
    30. modMap.put(numerator, start);
    31. // 计算分数
    32. numerator *= 10;
    33. sb.append(numerator / denominator);
    34. // 重新生成分子
    35. numerator %= denominator;
    36. start++;
    37. }
    38. // 判断是否存在循环小数
    39. Integer index = modMap.get(numerator);
    40. if (index != null) {
    41. // 使用insert操作,降低耗时
    42. sb.insert(index.intValue(), '(').append(')');
    43. }
    44. return sb.toString();
    45. }
    46. public static void main(String[] args) {
    47. Solution solution = new Solution();
    48. System.out.println(solution.fractionToDecimal(4, -333));
    49. System.out.println(solution.fractionToDecimal(4, 333));
    50. System.out.println(solution.fractionToDecimal(1, 2));
    51. System.out.println(solution.fractionToDecimal(2, 1));
    52. System.out.println(solution.fractionToDecimal(2, -1));
    53. }
    54. }

    总结

    这道题就是一个数学题目,我主要的时间花在判断循环小数上,最终还是看了其他人的解决思路后才做出来的。

    这个过程中遇到2个问题,一个是溢出问题,所以我这边最后使用long做计算。还有就是耗时问题,我开始是重新拷贝字符串再拼接循环小数,这样导致耗时很高,最后使用StringBuilder.insert耗时才降下来的。后续还是要多看看系统自带库函数,目前看都比自己实现的性能要好很多。如果有性能更好,设计更好的解决方案,欢迎回复。

  • 相关阅读:
    掏空了各大搜索引擎,整理了154道Java面试题!
    docker启动fastdfs
    ESP8266-Arduino编程实例-74HC595位移寄存驱动
    “行泊一体”的火爆与现实困境
    客快物流大数据项目(七十):Impala入门介绍
    mysql数据库,字符串使用双引号““导致报错,使用单引号‘‘不报错,Unknown column ‘user-test‘ in ‘where clause‘
    代码随想录训练营第42天|416.分割等和子集
    【FreeRTOS-----笔记(基础)】
    非肿瘤纯生信拿下7+,多种机器学习算法,搭配WGCNA。
    SQL注入-下篇
  • 原文地址:https://blog.csdn.net/weiliuhong1/article/details/126169055