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

Confusing f64 → Decimal #548

Open
loyd opened this issue Sep 7, 2022 · 2 comments
Open

Confusing f64 → Decimal #548

loyd opened this issue Sep 7, 2022 · 2 comments

Comments

@loyd
Copy link

loyd commented Sep 7, 2022

Example:

let f = 1652185258.8058286;
let a: Decimal = f.to_string().parse().unwrap();
let b = Decimal::try_from(f).unwrap();
let c = Decimal::from_f64_retain(f).unwrap();
println!("try_from(f64 -> str): {}", a);
println!("try_from(f64):        {}", b);
println!("from_f64_retain(f64): {}", c);
try_from(f64 -> str): 1652185258.8058286
try_from(f64):        1652185258.805829
from_f64_retain(f64): 1652185258.8058285713195800781

Can a direct conversion be improved? Or, at least, it should be noted in the documentation about such problems.
Maybe the crate should provide a special feature to have more expensive (but at least without allocation and with ryu) conversion by default.

@paupino
Copy link
Owner

paupino commented Sep 10, 2022

Interesting. I'll need to look into it some more - the second result (b) is unexpected, however the rest are expected results.

Floats are effectively an approximation and the default parsing route tries to alleviate this by rounding to the known precision boundary (in contrast, the _retain function skips the final rounding). I would expect the parsing, in this case, to round - however it seems like it has rounded to one less decimal place than expected (i.e. since it extracted 1652185258.8058285713195800781 it should knowingly round to 1652185258.8058286).

I'll take a look into it.

@paupino
Copy link
Owner

paupino commented Sep 10, 2022

I was slightly incorrect when I said it rounded to the known precision boundary - instead, it tries to round to what it deems as the floating point numbers "guaranteed" precision.

Getting this right is easier said than done. In the past, we were a little more relaxed when performing the rounding check however this allowed other issues to creep in: #229

I'll need to do some research to see if there are alternative algorithms that could potentially help however unfortunately it isn't a trivial task. In lieu of this, I'll likely update the documentation to describe how parsing works as well as known limitations.

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

2 participants