0

I've been attempting to convert a decimal number to a rational, where the decimal is an instance of BigDecimal. This works perfectly find for all terminating decimals, however non-terminating decimals cause rounding errors, and I don't know how to fix them.

The Code To Produce a Fraction:

public static Fraction of(BigDecimal bigDecimal, int decimalCutoff) {
    bigDecimal = bigDecimal.stripTrailingZeros(); //Get rid of excess zeros
    int n = 0; //Set up exponent
    while (!PlasmaBigMathUtil.isInteger(bigDecimal) && n <= decimalCutoff) { //Loop through and build up the exponent
        n++;
    }
    return new Fraction(bigDecimal.scaleByPowerOfTen(n).toBigInteger(), BigDecimal.ONE.scaleByPowerOfTen(n).toBigInteger()); //Return the decimal*10^n over 10^n
}

All tests for terminating fractions function as expected, and the isInteger method works fine. The problem is that when inputting something like 1/3 (3.33...), it outputs 3333333333333333/10000000000000000 (33333333333333330000000000000000000000000000000000000000000000000000000000000000000000000000000000000/100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 un-reduced).

The reduce method is as follows:

public void reduce() {
    BigInteger greater = PlasmaBigMathUtil.greatestCommonFactor(this.numerator, this.denominator);
    this.numerator = this.numerator.divide(greater);
    this.denominator = this.denominator.divide(greater);
}

And the greatest common factor is implemented like so (using Euclid's Algorithm) :

public static BigInteger greatestCommonFactor(BigInteger a, BigInteger b) {
    a = a.abs();
    b = b.abs();
    return b.equals(BigInteger.ZERO) ? a : PlasmaBigMathUtil.greatestCommonFactor(b, a.mod(b));
}

I expect there is some check I can do, or some rounding case I can handle to properly convert 1/3 to, well, 1/3, but I'm unsure of what that is. Any help would be greatly appreciated.

Socratic Phoenix
  • 556
  • 1
  • 7
  • 19
  • 1
    `PlasmaBigMathUtil`? Never heard of it. And what does this do other than increment `n`? `while (!PlasmaBigMathUtil.isInteger(bigDecimal) && n <= decimalCutoff) { n++; }` – TT. Feb 04 '16 at 22:30
  • PlasmaBigMathUtil is my class.. implementations of methods used are shown. The while loop does nothing other than increment n. It then uses n as an exponent for scaling by 10. – Socratic Phoenix Feb 04 '16 at 22:44
  • Did you mean to say that it works for terminating decimals, but gives a rounding error for non-terminating decimals? – Dawood ibn Kareem Feb 05 '16 at 12:08

0 Answers0