I've had an idea for a class that, instead of storing a number as a single floating-point value, stores the exact value as two or more integers (in cases such as division, fractional exponents, or irrational numbers such as pi or e). The class would have it's own mathematical functions as methods, modifying the internal values and possibly storing additional values as needed, and returning a double. The point would be to always have the exact value, only rounding when returning a value. This sounds like a good idea to me, but i haven't seen it done before. Does it exist and i simply haven't seen it, or is there some inherent flaw with this idea?

Dani AI

Generated

Good idea — the core notion (store exact structure instead of a single IEEE double) is sound. As suggested, the simplest useful case is to represent rationals as two integers (use BigInteger) and keep them reduced and canonical; that gives mathematically exact results for any operation that stays inside Q. ’s pointer to Java’s arbitrary-precision decimals was on the right track, and ’s comment points to why a different internal form is useful when you want exact rational math rather than decimal expansion.

Practical design notes you can apply immediately:

  • Keep a small type hierarchy: Integer(BigInteger), Rational(BigInteger num, BigInteger den), Symbolic(Constant like PI or E), Algebraic(minimal polynomial + root index) and Expression(operator, operands).
  • Always reduce rationals (g = num.gcd(den)), normalize sign, and use the canonical form for equals/hashCode to avoid explosion of distinct-but-equal objects.
  • For transcendental functions (exp, log, trig) either return a symbolic node that records the operation or convert to a controlled-precision BigDecimal; don’t try to manufacture an exact integer tuple for those.
  • Watch performance: numerators and denominators grow quickly; gcd and BigInteger ops are costly. Cache common subexpressions and simplify eagerly where possible.

Minimal Java skeleton for a fraction (start point):

import java.math.BigInteger;
import java.math.BigDecimal;
import java.math.RoundingMode;

public final class Fraction {
    private final BigInteger num, den;

    public Fraction(BigInteger n, BigInteger d) {
        if (d.signum() == 0) throw new ArithmeticException("divide by zero");
        BigInteger g = n.gcd(d);
        BigInteger n0 = n.divide(g);
        BigInteger d0 = d.divide(g);
        if (d0.signum() < 0) { n0 = n0.negate(); d0 = d0.negate(); }
        this.num = n0; this.den = d0;
    }

    public Fraction add(Fraction o) {
        return new Fraction(num.multiply(o.den).add(o.num.multiply(den)), den.multiply(o.den));
    }

    public double toDouble() {
        return new BigDecimal(num).divide(new BigDecimal(den), 34, RoundingMode.HALF_EVEN).doubleValue();
    }
}

If the goal is “perfect accuracy” across all operations, expect complexity: exact rationals are easy; algebraic numbers require more sophisticated representations; transcendental numbers force symbolic treatment. A hybrid approach (exact internally where possible; convert with controlled precision when needed) is usually the best tradeoff.

Recommended Answers

All 5 Replies

BigDecimal not work for you?

Well, when i looked at it before i posted this, it looked like it meant something completely different. I knew it existed somewhere. Thanks!

Big Decimal still won't give an exact value for rational numbers such as 1/3, so your idea may still be useful if you store numbers as exact fractions.

It makes sense that a BigDecimal couldn't return a fraction, but it does store an exact value, right? The only reason i can think of for it having it's own arithmetic methods would be that it stores it's values in a different way that would allow for exact values, but doesn't work with the regular "a=b+c".

but it does store an exact value, right?

Apparently not! This extract is from the BigDecimal JavaDoc

In the case of divide, the exact quotient could have an infinitely long decimal expansion; for example, 1 divided by 3. If the quotient has a nonterminating decimal expansion and the operation is specified to return an exact result, an ArithmeticException is thrown.

It looks like it stores numbers as an arbitrarily long sequence of digits, with the decimal point anywhere. That means it can't store exact values for n/3, n/7 etc. So maybe there's still an opportunity for you here...

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.