https://leetcode.com/problems/fraction-to-recurring-decimal/
Given two integers representing the numerator and denominator of a fraction, return the fraction in string format.
If the fractional part is repeating, enclose the repeating part in parentheses.
For example,
- Given numerator = 1, denominator = 2, return "0.5".
- Given numerator = 2, denominator = 1, return "2".
- Given numerator = 2, denominator = 3, return "0.(6)".
这道题本身不是太难,但是corner case太丧病了!
首先,求输出的正负,然后把输入的两个数都求绝对值(不然余数是负数,就没法接着算了),这里一定要注意,把除数和被除数全部变成long,不然会溢出。。。例如(INT_MIN, -1)这种。。。
而且一定要把输入变成long了之后再求绝对值,因为Math.abs(INT_MIN)是它本身!
另外,有一个hashtable记录出现过的余数值和这个余数出现的位置,当余数重复出现时,就说明开始循环了。
重复出现的余数在hashtable中记录的它第一次出现的位置就是循环开始的地方,循环结束的地方就是第一个重复余数之前的位置。
小数点后的每一位数都是当前的余数 (rest * 10)/demoninator得到的。这个在我们平时做除法的时候就能发现了。
0.00043464346不代表0或者4重复出现了就是循环结束了,而是余数重复出现了才是循环结束了。
代码如下:
public static String fractionToDecimal(int numerator, int denominator) {
StringBuilder rst = new StringBuilder();
if((numerator>0 && denominator < 0) || (numerator<0 && denominator > 0)) rst.append('-');
long num = Math.abs((long)numerator);
long den = Math.abs((long)denominator);
long intpart = num/den;
rst.append(intpart);
long rest = num%den;
if(rest!=0) rst.append('.');
else return rst.toString();
HashMap<Long, Integer> map = new HashMap<Long, Integer>();
String fraction = "";
int count = 0;
while(rest!=0){
if(!map.containsKey(rest)){
map.put(rest, count);
count++;
int digit = (int)((rest*10)/den); //calculate current result digit
fraction += Character.toString((char)(digit+'0'));
rest = (rest*10)%den; //calculate next residue
}
else{
int i = map.get(rest);
String nrpt = fraction.substring(0, i);
String rpt = fraction.substring(i, fraction.length());
fraction = nrpt + Character.toString('(') + rpt + Character.toString(')');
break;
}
}
rst.append(fraction);
return rst.toString();
}