Why is try_from not implemented for f64 to f32

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=d289972730bdd40752b36f22d18e617a

Can't do this:

let flong: f64 = 100.0;
let fwork = f32::try_from(flong);

It wouldn't be exact, so it's disallowed. But how do you do that conversion safely?

This reference says that using "as" on a n f64 to f32 is undefined behavior for out of range values and a known bug.

This Stack Overflow article fails to provide a solution.

So none of the obvious approaches work.

If you click on the GitHub issue that that site links, you'll see that it's closed. That site is out of date, you should use the reference instead:

  • Casting from an f64 to an f32 will produce the closest possible f32 **
    • if necessary, rounding is according to roundTiesToEven mode ***
    • on overflow, infinity (of the same sign as the input) is produced

** if f64-to-f32 casts with this rounding mode and overflow behavior are not supported natively by the hardware, these casts will likely be slower than expected.
*** as defined in IEEE 754-2008 §4.3.1: pick the nearest floating point number, preferring the one with an even least significant digit if exactly halfway between two floating point numbers.

The RFC for TryFrom was 1542. The topic was discussed here: GitHub. Casts involving floats were ultimately dropped including TryFrom for f64 -> f32. In my naive take, I suspect it has to do with a lack of a clear line for when to throw an error and method for rounding down to the f32 value in a canonical way.

I base this loosely on the authors’ referencing also not having f32 -> i32 because of a loss of precision.

For u64 -> u32 it’s clear when it makes sense to throw an error. Before the error needs to be thrown the values are semantically identical. That can’t be said for floats. The extra precision in a f64 vs a f32 actually means something - always. So, when do you throw an error, and how do you treat the loss of precision? There are ways, but none that are canonical.

I see. Depending on viewpoint, f64 -> f32 conversion could actually qualify for the actual From trait now.

There are the IEEE Floating Point flags, one of which is inexact, but I don't know if the libraries provide a way to set and check the flags. If there was, you could clear inexact, do the cast, and return an error if inexact was set. If inexact is set on conversions, that is.

1 Like

Do floats have a way to encode the number of significant digits? I suppose it makes sense I they do... That would change what I was thinking earlier.

What constitutes a significant digit depends on your calculation, so you need something like interval arithmetic to even get an estimate.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.