import java.util.HashMap
import java.util.Map
/**
* ref:https://leetcode-cn.com/problems/fraction-to-recurring-decimal/
* 给定两个整数,分别表示分数的分子numerator和分母denominator,以字符串形式返回小数。
* 如果小数部分为循环小数,则将循环的部分括在括号内。如果存在多个答案,只需返回任意一个。
* 对于所有给定的输入,保证答案字符串的长度小于104。
* 输入:numerator = 2, denominator = 3
* 输出:"0.(6)"
* 输入:numerator = 2, denominator = 1
* 输出:"2"
* 输入:numerator = 6, denominator = 50
* 输出:"0.12"
*/
public class FractionDecimal {
public static void main(String[] args){
System.out.println(fractionToDecimal(2,3))
System.out.println(fractionToDecimal(2,1))
System.out.println(fractionToDecimal(6,50))
}
/**
* 思路:
* 首先对分子和分母进行判断,如果分子是0,则输出“0”,如果分母是0,则输出“”。
* 然后判断,是否可以整除,如果可以整除,则直接使用字符串返回。
* 如果不可以整除,则需要分两种场景考虑,小数部分可以除尽和不可以除尽。
* 针对除尽的,比如6/50,先计算整数部分,6/50的整数部分为0,得到整数部分后,将其转换为字符串并加上小数点。
* 然后对余数6*10=60,在进行与50进行除,得到60/50=1计入字符串中,此时余数为10。
* 然后对余数10再次进行重复处理,10*10=100,对100/50=2的值计入字符串。
* 直到两个数取模是0,也就是整除了结束。
* 针对除不尽的,比如2/3,先计算整数部分,2/3的整数部分为0,得到整数部分后,将其转换为字符串并加上小数点。
* 然后对余数2*10=20,在进行对3进行除,得到6计入字符串中。对余数2再次进行重复处理,2*10=20,
* 对20/3=8的值计入字符串,此时发现每次余数都是固定的值2,则表示是循环除不尽。
* 除计算过程中,将余数和当前字符串长度进行缓存。当下次出现余数相同时,直接从缓存中获取字符串长度值进行插入括号。
* 代码逻辑,是对上述思路进行了整理后的合并
* @param numerator
* @param denominator
* @return
*/
public static String fractionToDecimal(int numerator, int denominator) {
// 对除数和被除数是0的判断
if(numerator==0) return "0"
if(denominator==0) return ""
// 正负数判断,如果有一个数是负数,则结果添加负号
StringBuilder result = new StringBuilder()
if((numerator>0&&denominator<0)||(numerator<0&&denominator>0)){
result.append("-")
}
// 先取绝对值
numerator = Math.abs(numerator)
denominator = Math.abs(denominator)
// 记录整数部分
result.append(numerator/denominator)
// 取模判断是否可以整除
int modNum = numerator%denominator
// 模值不是0,表示没有整除,肯定是有小数的,需要添加小数点
if(modNum!=0){
result.append(".")
}
// cache余数对应的字符串长度
Map<Integer, Integer> modMap = new HashMap<>()
// 开始计算小数部分
while(modNum!=0){
// 缓存当前余值对应的字符串在进行当前取余之前的长度,用于当整除不尽时,每次余数相同时,添加(使用。
modMap.put(modNum,result.length())
// 计算本轮数除进行除数据后的值,乘以10是用于进位
int currentMod = modNum * 10
result.append(currentMod/denominator)
// 从新计算本轮值对除数的余数,如果余数在map中存在,则表示已循环。使用()
modNum = currentMod%denominator
if(modMap.get(modNum)!=null){
return result.insert(modMap.get(modNum),"(").append(")").toString()
}
}
return result.toString()
}
}