🌕🌕 166. 分数到小数
2022年10月10日
- algorithm
🌕🌕 166. 分数到小数
难度: 🌕🌕
问题描述
解法
class Solution {
public String fractionToDecimal(int numerator, int denominator) {
// 思路:
// HashMap 存放已经计算过的分母值,判断是否出现重复元素
if(numerator == 0) {
return "0";
}
// 为防止超范,转化为 long
long a = (long) numerator;
long b = (long) denominator;
boolean pos = true;
if((a > 0 && (b < 0)) || (a < 0 && b > 0)) {
pos = false;
a = a >= 0 ? a: -a;
b = b >= 0 ? b: -b;
}
StringBuilder sb = new StringBuilder();
long cur = a % b * 10; // 从小数部分开始记录
long partInt = a / b; // 计算整数部分
sb.append(partInt);
// 能被整除,直接返回
if(cur == 0) {
if(!pos) {
sb.insert(0, '-');
}
return sb.toString();
}
// 不能被整除,计算小数部分
sb.append('.'); // 加小数点
if(!pos) {
sb.insert(0, '-'); // 加负号
}
// System.out.println(partInt + " : " + cur);
int havIndex = sb.length(); // 当前 sb 已有长度,记录下标从这里开始
HashMap<Long, Integer> map = new HashMap<>();
map.put(cur, havIndex); // val - 存放下标
boolean flag = false; // 判断是否出现循环
String circle = "";
int curIndex = havIndex;
while(cur != 0) {
long app = cur / b;
sb.append(app); // 先不管小数点,最后判断,只要有前导0,那么小数点就在第一个 0 后面
curIndex ++;
long next = cur % b * 10;
// System.out.println(sb.toString() + " " + cur + " " + next);
if(map.containsKey(next)) {
// 出现循环
int preIndex = map.get(next); // 查看上一次出现该值的下标是多少
circle = sb.substring(preIndex, curIndex);
flag = true;
break;
} else {
map.put(next, curIndex);
}
cur = next;
}
// System.out.println(sb.toString() + " " + circle);
// 添加小数部分的循环,由于已经得出循环,所以实际上添加的是两边的括号
if(flag) {
sb.insert(sb.length() - circle.length(), '(');
sb.append(')');
}
return sb.toString();
}
}