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

问题描述 投票:5回答:2

我想知道值是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);
}

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

println!("{}", 0.4);     // prints "0.4"
println!("{:.20}", 0.4); // prints "0.40000000000000002220"

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

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

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

rust floating-point ieee-754
2个回答
3
投票

来自Rationalrug crate类型可以精确地表示分数。它还实现了PartialEq<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);
}

正如您从输出中看到的那样,您要测试的数字确实可以代表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);
}

这表明只有具有2次幂分母的分数才能准确表示。


0
投票

你需要更高精度的计算(f64是明显的和最快的,但有其他选择:例如f128BigDecimalrug's rationalfloatetc.),然后检查结果是否等于自身转换为f32并返回。

为了举个例子,假设f64

d.is_finite() && (d as f32) as f64 == d

当然,正如Jojonete的评论指出的那样,这些计算的结果可能最终完全可以表示为f32,即使确切的结果不会。所以你想要的数据类型将取决于计算。例如。对于

1 / 256,2 / 256,3 / 256,...... 254/256和255/256

rug::rational肯定是准确的(f64也是如此,但是你需要“考虑浮点数如何工作并找出那种方式”至少一点)。

© www.soinside.com 2019 - 2024. All rights reserved.