dnsl48 / fraction

[Rust] Lossless fractions and decimals; drop-in float replacement
Apache License 2.0
83 stars 25 forks source link

.pow() and .root() functions for fraction types #60

Open Gip-Gip opened 2 years ago

Gip-Gip commented 2 years ago

I'm currently writing a basic calculator with this library and I noticed at the moment there is no .pow() or .root() style functions for fractions.

Also when performing square roots should they simply be approximated or should numbers simply represent simplified square roots, popping all of the irrational roots in a vector or something like that. For example, something like this

let foo = Fraction::from(75u32);
let result = foo.sqrt();
assert_eq!(5, result.get_base_multiplicand()); // Not actually functional code just here to get a point across
assert_eq!(3, result.get_root_multipliers()[0]);
println!("{:9}", result); // -> 8.660254037

I would like to contribute I'm just unsure how as to go about tackling this problem, at the moment

dnsl48 commented 2 years ago

Hi @Gip-Gip, thank you for your interest and your support!

Regarding pow, I feel like we may consider falling back to num-rational pow implementation. Fraction is built on top of Rational type already, so this may be the eastiest path forward

Not too sure about sqrt. That feels somewhat more challenging. I guess you may have a real-world problem on your hands, so we'd be happy to consider a way that would solve your current challenge.

One of the primary goals of this library is to provide lossless math, so I am not too sure if an approximation would follow that direction. However, if we explicitly call that out in the function name (e.g. sqrt_approx), I think that should be totally alright.

Gip-Gip commented 2 years ago

I'll look into experimenting with a few options over the next few days or so. A good .pow function would look something like

fn pow(left: Fraction, right: Fraction) -> Fraction {
    let exp = right.numer().unwrap().clone();
    let root = right.denom().unwrap().clone();

    // Insert code here where result = nthroot(left^exponent, root)

    return result
}
feefladder commented 11 months ago

I've been working on a crate heavily building on top of the fraction crate for exact arithmetic. the relevant code is here first handle special cases such as infinity or nan, then do the calculation. It's inside match statements, but should be quite copy-pasteable into this crate.