分数与无限循环小数的相互转换

       分数转化为小数如果不是有限的,那么必然是无限循环小数,原因很简单:对于一个分数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]"));
	}
	
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值