在Java中加倍分数

所以我要做的是将double转换为有理数。 我检查小数点后有多少位数,我想将数字123.456保存为123456/1000,例如。

public Rational(double d){ String s = String.valueOf(d); int digitsDec = s.length() - 1 - s.indexOf('.'); for(int i = 0; i < digitsDec; i++){ d *= 10; } System.out.println((int)d); //checking purposes } 

但是,对于数字123.456,我得到一个舍入错误,结果是123455.我想有可能用BigDecimal解决这个问题,但我无法让它工作。 此外,计算了它的有理数,我想调用另一个带参数的构造函数(int numerator,int denominator),但我现在无法在println所在的行中调用构造函数。 我该怎么做?

对于问题的第一部分,Java将.6存储为.5999999(重复)。 看到这个输出:

 (after first multiply): d=1234.56 (after second multiply): d=12345.599999999999 (after third multiply): d=123455.99999999999 

一个解决方法是在循环结束后立即使用d = Math.round(d)。

 public class Rational { private int num, denom; public Rational(double d) { String s = String.valueOf(d); int digitsDec = s.length() - 1 - s.indexOf('.'); int denom = 1; for(int i = 0; i < digitsDec; i++){ d *= 10; denom *= 10; } int num = (int) Math.round(d); this.num = num; this.denom = denom; } public Rational(int num, int denom) { this.num = num; this.denom = denom; } public String toString() { return String.valueOf(num) + "/" + String.valueOf(denom); } public static void main(String[] args) { System.out.println(new Rational(123.456)); } } 

它有效 - 尝试一下。

对于你问题的第二部分......

为了从第一个构造函数调用第二个构造函数,可以使用“this”关键字

 this(num, denom) 

但它必须是构造函数中的第一行...这在这里没有意义(我们必须先做一些计算)。 所以我不打算尝试这样做。

这段代码对你来说可能有点过分,但是它会处理你正在经历的舍入错误,它还会处理重复的小数(4.99999999999999变成5,而0.33333333333333333333变成1/3)。

 public static Rational toRational(double number){ return toRational(number, 8); } public static Rational toRational(double number, int largestRightOfDecimal){ long sign = 1; if(number < 0){ number = -number; sign = -1; } final long SECOND_MULTIPLIER_MAX = (long)Math.pow(10, largestRightOfDecimal - 1); final long FIRST_MULTIPLIER_MAX = SECOND_MULTIPLIER_MAX * 10L; final double ERROR = Math.pow(10, -largestRightOfDecimal - 1); long firstMultiplier = 1; long secondMultiplier = 1; boolean notIntOrIrrational = false; long truncatedNumber = (long)number; Rational rationalNumber = new Rational((long)(sign * number * FIRST_MULTIPLIER_MAX), FIRST_MULTIPLIER_MAX); double error = number - truncatedNumber; while( (error >= ERROR) && (firstMultiplier <= FIRST_MULTIPLIER_MAX)){ secondMultiplier = 1; firstMultiplier *= 10; while( (secondMultiplier <= SECOND_MULTIPLIER_MAX) && (secondMultiplier < firstMultiplier) ){ double difference = (number * firstMultiplier) - (number * secondMultiplier); truncatedNumber = (long)difference; error = difference - truncatedNumber; if(error < ERROR){ notIntOrIrrational = true; break; } secondMultiplier *= 10; } } if(notIntOrIrrational){ rationalNumber = new Rational(sign * truncatedNumber, firstMultiplier - secondMultiplier); } return rationalNumber; } 

这提供了以下结果(测试用例的结果显示为注释):

 Rational.toRational(110.0/3.0); // 110/3 Rational.toRational(11.0/1000.0); // 11/1000 Rational.toRational(17357.0/33300.0); // 17357/33300 Rational.toRational(215.0/21.0); // 215/21 Rational.toRational(0.123123123123123123123123); // 41/333 Rational.toRational(145731.0/27100.0); // 145731/27100 Rational.toRational(Math.PI); // 62831853/20000000 Rational.toRational(62.0/63.0); // 62/63 Rational.toRational(24.0/25.0); // 24/25 Rational.toRational(-24.0/25.0); //-24/25 Rational.toRational(-0.25333333333333333333333); // -19/75 Rational.toRational(-4.9999999999999999999999); // -5 Rational.toRational(4.9999999999999999999999); // 5 Rational.toRational(123.456); // 15432/125 

然而,它并不优雅,我相信这就是你所要求的。

 double a = 123.456; String aString = Double.toString(a); String[] fraction = aString.split("\\."); int denominator = (int)Math.pow(10, fraction[1].length()); int numerator = Integer.parseInt(fraction[0] + "" + fraction[1]); System.out.println(numerator + "/" + denominator); 

这里,d = 123.456,然后num = 123456,j = 1000

 public Rational(double d){ double temp =d; int j=1, num; do{ j=j*10; }while((temp*j)%10==0); j=j/10; num=(int)(d*j); System.out.println(num); System.out.println(j); } 

尝试

 for(int i = 0; i <= digitsDec; i++){ }