Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Casting `f32::MAX` to `u128` results in unexpected value

Tags:

casting

rust

Executing this code (Playground):

println!("u128 max:    {}", u128::max_value());
println!("f32 max:     {}", std::f32::MAX);
println!("f32 as u128: {}", std::f32::MAX as u128);

... prints:

u128 max:    340282366920938463463374607431768211455
f32 max:     340282350000000000000000000000000000000
f32 as u128: 340282346638528859811704183484516925440

Judging from this output, we can deduce that u128::max_value() > f32::MAX and that f32::MAX is an integer (without fractional part). Indeed, Wikipedia agrees with the max values and says that f32::MAX is (2 − 2−23) × 2127 which is slightly less than 2128. Given that, I would think that f32::MAX is exactly representable as u128. But as you can see, casting it via as gives an entirely different value.

Why does the result of the cast differ from the original value?

(I know that floats are very strange beasts and all. But I hope that there is an answer to this question that contains more information than "floats are strange duh")

like image 957
Lukas Kalbertodt Avatar asked Feb 04 '19 14:02

Lukas Kalbertodt


1 Answers

This is due to the formatting of the float when you are printing it. It seems by default the formatter will only show 8 significant figures when printing floats. Explicitly specifying the precision in the format string will yield the same results for line 2 and 3.

println!("u128 max:    {}", u128::max_value());
println!("f32 max:     {:.0}", std::f32::MAX);
println!("f32 as u128: {}", std::f32::MAX as u128);

Outputs:

u128 max:    340282366920938463463374607431768211455
f32 max:     340282346638528859811704183484516925440
f32 as u128: 340282346638528859811704183484516925440
like image 100
Marcus Avatar answered Oct 15 '22 04:10

Marcus