[][src]Function libslide::math::fraction::dec2frac

pub fn dec2frac(num: f64, max_iter: u64) -> Result<(i64, u64), Dec2FracError>

Converts a decimal number to its irreducible fractional representation by walking the Stern-Brocot tree. This is equivalent to a binary search of the Farey sequence.

Algorithm

Say we are looking for a number A, where A = Whole + Decimal, Whole ∈ W, and Decimal ∈ [0, 1). Then if we can find T and B such that Decimal = T / B, A = Whole + Decimal = (Whole * B) / B + (T / B) = (Whole * B + T) / B

To find T and B we perform a binary search of irreducible fractions starting with the range [0, 1]. On each iteration of the search, we compute the mediant of the range.

mediant(A / B, C / D) = (A + C) / (B + D)

The mediant of two fractions is guaranteed to be between those two fractions, though is not always the median of those two fractions.

In the Stern-Brocot tree, the mediant of two sibling tree nodes is an irreducible fraction.

                      * ~ T / B
0 / 1 ----------------------|---------------------- 1 / 1
                          1 / 2 ~ mediant

We then bisect the search to the medaint-bound range the decimal we are interested in.

                                   * ~ T / B
0 / 1 -----------------------------|--------------- 1 / 2
                                 1 / 3 ~ mediant

We stop when the mediant is equivalent to the decimal searched for.

Failure

This algorithm is iterative and convergent, but terminates after max_iter iterations. If a fractional representation equivalent to the decimal at floating point precision cannot be found after max_iter, nothing is returned.

Examples

This example is not tested
assert_eq!(dec2frac(0.5, 10), Some((1, 2)))
assert_eq!(dec2frac(3.14159265358979323, 10), None)
assert_eq!(dec2frac(-3.142857142857142857, 100_000), Some((-22, 7)))