Open tgross35 opened 4 months ago
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.
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: https://github.com/rust-num/num-rational/issues/10