给定两个整数,分别表示分数的分子 numerator 和分母 denominator,以字符串形式返回小数。
如果小数部分为循环小数,则将循环的部分括在括号内。
示例 1:
输入: numerator = 1, denominator = 2
输出: "0.5" 示例 2:
输入: numerator = 2, denominator = 1
输出: "2"
示例 3:
输入: numerator = 2, denominator = 3
输出: "0.(6)"
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/fraction-to-recurring-decimal 著作权归领扣网络所有。
算法
需要用一个哈希表记录余数出现在小数部分的位置,当你发现已经出现的余数,就可以将重复出现的小数部分用括号括起来。
再出发过程中余数可能为 0,意味着不会出现循环小数,立刻停止程序。
就像两数相除问题一样,主义考虑负分数以及极端情况。
1 public String fractionToDecimal(int numerator, int denominator) {
2 if(numerator == 0) return "0"; //分子为零返回“0”
3
4 StringBuilder res = new StringBuilder();
5
6 if(numerator < 0 ^ denominator < 0) res.append("-");
7
8 //int的取值范围为(-2147483648~2147483647)
9 //如果int负最大值除以负一:-2147483648/-1 = 2147483648 、
10 //或者-1/-2147483648 超出了范围,所以转为long型
11
12 long up = Math.abs(Long.valueOf(numerator)); //且变为正数,因为前面已经判断了加负号的情况
13 // int up = Math.abs(numerator);
14 long down = Math.abs(Long.valueOf(denominator));
15 // int down = Math.abs(denominator);
16 //把整除部分先加上
17 res.append(String.valueOf(up/down));
18 //记录余数
19 long remain = up%down;
20 if(remain == 0) return res.toString();
21 res.append("."); //不能整除就要加小数点了
22
23 //创建一个map存余数和对应余数所在位置
24 Map<Long,Integer> map = new HashMap<>();
25 while(remain != 0){ //余数为零的话说明小数后面除得尽!
26 if(map.containsKey(remain)){ //发现这个余数之前有记录即产生了循环,循环处理加()
27 res.insert(map.get(remain),"(");
28 res.append(")");
29 break;
30 }
31 map.put(remain,res.length()); //记录当前余数和得到该余数的下一个分位,举个例子2/3就明白了
32 remain *=10; //余数加零再除
33 res.append(String.valueOf(remain/down));
34 remain %= down; //余数加零再求余
35
36 }
37 return res.toString();
38 }