I wondered whether the values 1/256, 2/256, 3/256, ... 254/256 and 255/256 are exactly representable as f32
. Now, someone smart would think about how floating point numbers work and find out that way. But I would like to check that in a program. All numbers I want to check are fractions and I control the values (i.e. no user input).
I started with this:
for n in 1u8..=255 {
let f = (n as f32) / 256.0;
println!("{}", f);
}
But now what? I tried printing the number to see if there were a large number of recurring digits, but that doesn't always work. For example, 0.4 which is not exactly representable:
println!("{}", 0.4); // prints "0.4"
println!("{:.20}", 0.4); // prints "0.40000000000000002220"
Here we have to manually crank up the precision to see the problems. And in any case, looking at the string output seems like a suboptimal solution anyway.
First I thought that there might be a method on f32
, but this wouldn't make much sense, would it? Because when a f32
already exists, there is no way to know if its value was intended or not. So we somehow have to find out when creating the float value and compare to the "idealized" value?
Is there any way to check if a value can be exactly represented as f32
?
Additionally, f32 can represent some special values: −0.0: IEEE 754 floating point numbers have a bit that indicates their sign, so −0.0 is a possible value. For comparison −0.0 = +0.0, but floating point operations can carry the sign bit through arithmetic operations.
A 32-bit floating point type (specifically, the “binary32” type defined in IEEE 754-2008). This type can represent a wide range of decimal numbers, like 3.5, 27 , -113.75, 0.0078125, 34359738368, 0, -1.
Therefore, the required answer is Yes. Approach: The idea is to store the perfect cubes of all numbers from 1 to cubic root of N in a Map and check if N can be represented as the sum of two numbers present in the Map or not. Follow the steps below to solve the problem:
However, being able to represent this wide range of numbers comes at the cost of precision: floats can only represent some of the real numbers and calculation with floats round to a nearby representable number.
The type Rational
from the rug
crate can represent fractions exactly. It also implements PartialEq<f32>
so you can compare the exact representation with your f32
directly to check if they are equal.
for n in 1u8..=255u8 {
let rat = Rational::from((n, 256));
let f = (n as f32) / 256.0;
println!("{}/256 -> {}", n, rat == f);
}
And as you can see from the output, the numbers you want to test are indeed exactly representable as f32
.
To get more a more interesting output, try 1 / n
:
for n in 1u8..=255u8 {
let rat = Rational::from((1, n));
let f = 1.0 / (n as f32);
println!("1/{} -> {}", n, rat == f);
}
This shows that only fractions with a power-of-2 denominator are exactly representable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With