Hello Heinrich.

Le ven. 5 juil. 2019 à 23:09, Heinrich Bohne <[email protected]> a écrit :
>
> Hello!
>
> I think a re-design of the factory method BigFraction.from(double,
> double, int, int) is in order, because I see several problems with it:
>
> First, having a separate fraction class intended to overcome the
> limitations of the int range with a factory method (formerly a
> constructor) for approximating double values that can only produce
> denominators within the int range because it has been copy-pasted from
> Fraction (where this code is still a constructor) seems a bit like a
> joke. I think it would be more useful to have this method accept a
> BigInteger as an upper bound for the denominator instead of an int.
>
> Second, the method only calculates the convergents of the corresponding
> continued fraction, but never its semi-convergents, so it doesn't
> necessarily produce the best rational approximation of the double number
> within the given bounds. For example, the test method
> BigFractionTest.testDigitLimitConstructor() asserts that the method
> calculates 3/5 as an approximation of 0.6152 with the upper bound for
> the denominator set to 9, but 5/8 = 0.625 is closer to 0.6152 than 3/5 =
> 0.6. Since the method is already using continued fractions to
> approximate fractional numbers, I think it would be a pity if it didn't
> take advantage of them for all that they're worth.
>
> Finally, the documentation of the method rightfully acknowledges the
> latter's confusing design, with the method's general behavior being
> dependent on some of its arguments and the validity of these arguments
> also being dependent on each other. However, a better way to solve this
> problem than to simply hide the design from the public would be to
> improve it, e.g. by extracting the functionality that is common to both
> the "maxDenominator mode" and the epsilon mode (which is the calculation
> of the continued fraction), and separating the differences in the
> functionality of the two modes into distinct methods that call the
> common functionality.
>
> My suggestion for the third point above would be to create a separate
> class (not necessarily public) that provides an interface for
> calculating simple continued fractions and their convergents (I see that
> there's an abstract class ContinuedFraction, but I don't think it will
> be useful, because all the methods only return double values, and the
> class also requires that all coefficients can be explicitly calculated
> based on their index). The class would ideally be able to calculate the
> continued fraction dynamically/lazily, because only a limited number of
> coefficients are needed to approximate a fractional number within given
> bounds. What I think could be useful is if the class stores a list of
> the coefficients internally in addition to the current and previous
> convergent (two consecutive convergents are needed to calculate the next
> one recursively based on the next coefficient), and has methods like
> addCoefficient(BigInteger) and removeLastCoefficient() for building a
> continued fraction, and also a static method like
> coefficientsOf(BigFraction) that returns an Iterator<BigInteger> that
> computes the coefficients only as they are queried through the iterator,
> so that they can then be passed to addCoefficient(BigInteger).
>
> The maxDenominator factory method could then just iterate over the
> coefficients of the continued fraction representation of the passed
> double and build the continued fraction from them until the denominator
> of the current convergent exceeds the upper bound, and the epsilon
> method could iterate over the coefficients of both the lower and upper
> bound's continued fraction representation until the coefficients start
> to differ, at which point it can build the continued fraction of the
> close enough approximation from all coefficients at once (this would
> also prevent any loss of precision when repeatedly performing arithmetic
> operations with floating-point values).
>
> Furthermore, this code could not only be used by the approximation
> factory methods in BigFraction, but also by those in Fraction, possibly
> adjusted so that not only the denominator must be within a given bound,
> but also the numerator needs to be within the int range.
>
> Any opinions or objections?

Thanks a lot for these suggestions.  It seems like a plan towards better
consistency, increased robustness and higher precision.

Best,
Gilles

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to