Double fraction in Java

So what I'm trying to do is convert double to a rational number. I check how many digits there are after the decimal point, and I want, for example, to keep the number 123.456 as 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 } 

However, for number 123.456, I get a rounding error, and the result is 123455. I think it could be fixed with BigDecimal, but I can't get it to work. Besides, having calculated what this rational number would be, I would like to name another constructor with parameters (int numator, int denominator), but I cannot explicitly call the constructor on the line where println is now. How can I do it?

+4
source share
5 answers

In the first part of the question, Java stores .6 as .5999999 (repeats). See this conclusion:

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

One fix is ​​to use d = Math.round (d) right after the loop ends.

 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)); } } 

It works - try it.

For the second part of your question ...

To call the second constructor from the first, you can use the keyword "this"

 this(num, denom) 

But it should be the very first line in the constructor ... which makes no sense here (first we need to do some calculations). Therefore, I would not try to do it.

+5
source

This code may be redundant for you, but it deals with the rounding error that you experience, and it also takes care of the fractions (+ 4.99999999999999 turns into 5, and 0.33333333333333333333 turns into 1/3) .P>

 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; } 

This gives the following results (test results are shown as comments):

 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 
+3
source

However, this is not elegant, I believe that it does what you ask.

 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); 
+2
source

Here d = 123.456, then 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); } 
+1
source

Try

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

All Articles