目录
题目
给定两个整数,分别表示分数的分子 numerator 和分母 denominator,以 字符串形式返回小数 。如果小数部分为循环小数,则将循环的部分括在括号内。
如果存在多个答案,只需返回 任意一个 。
对于所有给定的输入,保证 答案字符串的长度小于 10^4 。
分析 长除法
分数化小数,可能的结果有三种:整数、有限小数、无限循环小数。
先判断分子/分母能不能整除,可以就直接返回
否则,先判断一下结果的正负号
再对分子分母取绝对值,整除一下就得到了整数部分
关键是小数部分
取分子/分母的余数,乘10,再除分母,可得到一位小数。除分母留下的余数,再乘10...就这样一直循环算小数。
那么,什么时候停止呢?
①余数*10/分母能够整除,说明它是有限小数
②我们在上面循环的时候,将每一轮循环的余数*10这个数,存到一个map对象中
当我们发现map对象中开始有重复值了,就停止循环,说明它有循环节,是无限循环小数
保存这个第一个开始重复的值,也就是循环节的第一个字符,用来规范结果的格式。
/**
* @param {number} numerator
* @param {number} denominator
* @return {string}
*/
var fractionToDecimal = function(numerator, denominator) {
// 如果结果为整数
if(numerator % denominator == 0) {
return '' + numerator / denominator;
}
const sb = [];
// 判断结果的符号
if(numerator < 0 ^ denominator < 0) {
sb.push('-');
}
// 整数部分
numerator = Math.abs(numerator)
denominator = Math.abs(denominator);
const integerPart = Math.floor(numerator / denominator);
sb.push(integerPart);
sb.push('.');
// 小数部分
const fractionPart = [];
const remainderIndecDic = new Map();
let remainder = numerator % denominator;
let index = 0;
while(remainder !== 0 && !remainderIndecDic.has(remainder)) {
remainderIndecDic.set(remainder, index);
remainder *= 10;
fractionPart.push(Math.floor(remainder / denominator));
remainder %= denominator;
index++;
}
// 小数部分有循环节
if(remainder !== 0) {
let insertIndex = remainderIndecDic.get(remainder);
fractionPart.splice(insertIndex, 0,'(');
fractionPart.push(')');
}
sb.push(fractionPart.join(''));
return sb.join('');
};