分数转化为小数如果不是有限的,那么必然是无限循环小数,原因很简单:对于一个分数p/q,由于q是有限的,模q的结果也是有限的,而得到p/q结果的过程,可以看做0—q-1个数中的一个构成p,迭代p/q的过程,所以必然会出现循环,如果结果是无限的,必然为无限循环小数。
这里就无限循环小数与其对应的分数用java语言来实现其转换过程,其中的无限循环小数的表示形式满足正则表达式“\d\.\d*\[\d{m}\]”,例 0.[3]是分数1/3的无限循环表示,[]中为循环节。其转换原理较为简单,网上随便搜索即可得,故这里不做细究。其代码如下:望批评指正。
package com.yh.math;
import java.util.Arrays;
public class FractionAndRecurringDecimal {
/**
* get lcm of x and y
*
* @param x
* @param y
* @return lcm of x and y,the type is long
*/
public static long getLcm(long x,long y){
if(x<y)
return getLcm(y,x);
if(y == 0){
System.out.println("ErrorMsg:@Lcd method the parameters are wrong!");
return 0;
}
long remainder = x % y;
if(remainder == 0)
return y;
else
return getLcm(y,remainder);
}
/**
* from a fraction to a finite or unfinite recurring decimal
*
* @param numInt numerator
* @param denoInt denominator
* @return String the recurring decimal of the fraction
*/
public static String fra2RecDec(int numInt , int denoInt ){
int divider = numInt / denoInt;
numInt = numInt % denoInt;
int lcm = (int)getLcm(numInt,denoInt);
if(lcm != 1 && lcm != 0){
numInt = numInt / lcm;
denoInt = denoInt / lcm;
}
boolean markArr[] = new boolean[denoInt*10];
int resuArr[] = new int[1000];
int resuIndex[] = new int[denoInt*10];
Arrays.fill(markArr, false);
Arrays.fill(resuArr, -1);
Arrays.fill(resuIndex, -1);
int startIndex = -1;
int index = -1;
numInt = numInt * 10;
while(true){
index++;
int remainder = numInt %denoInt;
if(remainder == 0)
break;
if(markArr[numInt]){
startIndex = resuIndex[numInt];
break;
}
else{
markArr[numInt] = true;
resuIndex[numInt] = index;
}
resuArr[index] = numInt / denoInt;
numInt = remainder * 10;
}
StringBuffer resuSB = new StringBuffer();
resuSB.append(divider);
resuSB.append(".");
for(int i=0;i<denoInt;i++){
if(resuArr[i] == -1)
break;
if(i == startIndex)
resuSB.append("[");
resuSB.append(resuArr[i]);
}
if(startIndex != -1)
resuSB.append("]");
return resuSB.toString();
}
/**
* get the result of the pow(10,index)
*
* @param index
* @return pow(10,index)
*/
private static long getTenBasePow(int index){
return (long)Math.pow(10, index);
}
/**
* get a number which every digit of the number is the same digit,
* and the length is index
*
* @param index the length of the number
* @param data the same data
* @return long
*/
private static long getAsideData(int index,int data){
long resu = 0;
for(int i=0;i<index;i++){
resu = resu*10 + data;
}
return resu;
}
/**
* from a recurring decimal to fraction
*
* @param recDecStr the recurring decimal
* @return fraction
*/
public static String recDec2Fra(String recDecStr){
int dotPos = recDecStr.indexOf(".");
int leftBrcPos = recDecStr.indexOf("[");
int rightBrcPos = recDecStr.indexOf("]");
if(dotPos == -1 || leftBrcPos == -1 || rightBrcPos == -1){
System.out.println("ErrorMsg:@recDec2Fra method the parameters are wrong!");
}
int preNum = leftBrcPos - dotPos - 1 ;
int recNum = rightBrcPos - leftBrcPos - 1;
long intData = Integer.parseInt(recDecStr.substring(0, recDecStr.indexOf(".")));
long preData = 0;
if(preNum != 0)
preData = Integer.parseInt(recDecStr.substring(dotPos+1,leftBrcPos));
long recData = Integer.parseInt(recDecStr.substring(leftBrcPos+1,rightBrcPos));
long numLong = recData * (preNum ==0?1:preData);
long denoLong = getTenBasePow(preNum) * getAsideData(recNum,9);
long lcm = getLcm(numLong,denoLong);
if(lcm != 0 && lcm != 1){
numLong = numLong / lcm;
denoLong = denoLong / lcm;
numLong = numLong + intData * denoLong ;
}
return numLong + "/" + denoLong;
}
//test the functions
public static void main(String args[]){
System.out.println(fra2RecDec(16, 7));
System.out.println(recDec2Fra("2.[285714]"));
}
}