检查一个数字是否可以完全表示为`f32`

Luk*_*odt 6 floating-point ieee-754 rust

我想知道值是1/256,2/256,3/256,...... 254/256和255/256是否完全可以表示为f32.现在,聪明的人会考虑浮点数如何工作并找出那种方式.但我想在一个程序中检查一下.我要检查的所有数字都是分数,我控制值(即没有用户输入).

我从这开始:

for n in 1u8..=255 {
    let f = (n as f32) / 256.0;
    println!("{}", f);
}
Run Code Online (Sandbox Code Playgroud)

但现在呢?我尝试打印数字,看是否有大量的重复数字,但这并不总是有效.例如,0.4不完全可表示:

println!("{}", 0.4);     // prints "0.4"
println!("{:.20}", 0.4); // prints "0.40000000000000002220"
Run Code Online (Sandbox Code Playgroud)

在这里,我们必须手动提高精度以查看问题.无论如何,无论如何,查看字符串输出似乎是次优解决方案.

首先我认为可能有一种方法f32,但这没有多大意义,是吗?因为当f32已经存在时,无法知道其值是否有意.因此,我们必须找出何时创建浮点值并与"理想化"值进行比较?

有没有办法检查一个值是否可以准确表示为f32

Luk*_*odt 5

板条箱Rational中的类型可以准确地表示分数。它还实现了这样您就可以直接将确切的表示与您的表示进行比较,以检查它们是否相等。rugPartialEq<f32>f32

for n in 1u8..=255u8 {
    let rat = Rational::from((n, 256));
    let f = (n as f32) / 256.0;
    println!("{}/256 -> {}", n, rat == f);
}
Run Code Online (Sandbox Code Playgroud)

正如您从输出中看到的,您想要测试的数字确实可以完全表示为f32

要获得更多更有趣的输出,请尝试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);
}
Run Code Online (Sandbox Code Playgroud)

这表明只有分母为 2 次方的分数才能精确表示。