Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the ability to parse decimals into Ratio #131

Open
tgross35 opened this issue Jun 30, 2024 · 1 comment
Open

Add the ability to parse decimals into Ratio #131

tgross35 opened this issue Jun 30, 2024 · 1 comment

Comments

@tgross35
Copy link

tgross35 commented Jun 30, 2024

Would it be possible to parse decimals into rationals? Python has a way to do this to their Fraction, And Julia has a roundabout way to do this.

E.g. let x: BigRational = "1234.45e67".parse().unwrap()

Discussion about the inverse: #10

@tgross35 tgross35 changed the title Add the ability to pare decimals Add the ability to pare decimals into Ratio Jun 30, 2024
@tgross35 tgross35 changed the title Add the ability to pare decimals into Ratio Add the ability to parse decimals into Ratio Jun 30, 2024
@tgross35
Copy link
Author

tgross35 commented Jun 30, 2024

Helper I am using to do this for BigRational:

fn parse_rational(s: &str) -> BigRational {
    let mut s = s; // lifetime rules

    // Fast path; no decimals or exponents ot parse
    if s.bytes().all(|b| b.is_ascii_digit() || b == b'-') {
        return BigRational::from_str(s).unwrap();
    }

    let mut ten_exp: i32 = 0;

    // Remove and handle e.g. `e-4`, `e+10`, `e5` suffixes
    if let Some(pos) = s.bytes().position(|b| b == b'e') {
        let (dec, exp) = s.split_at(pos);
        s = dec;
        ten_exp = exp[1..].parse().unwrap();
    }

    // Remove the decimal and instead change our exponent
    // E.g. "12.3456" becomes "123456 * 10^-4"
    let mut s_owned;
    if let Some(pos) = s.bytes().position(|b| b == b'.') {
        ten_exp = ten_exp
            .checked_sub((s.len() - pos - 1).try_into().unwrap())
            .unwrap();
        s_owned = s.to_owned();
        s_owned.remove(pos);
        s = &s_owned;
    }

    let mut r = BigRational::from_str(s).unwrap();
    r *= BigRational::from_u32(10).unwrap().pow(ten_exp);
    r
}

This algorithm is simple but seems like it would run into overflow issues easily with sized ratios.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant