Rust中两个浮点数与任意精度的比较

时间:2017-01-03 16:12:43

标签: rust

如何以任意精度水平进行比较,以便我可以看到两个数字相同?在Python中,我会使用类似round()的函数,所以我在Rust中寻找相同的东西。

例如我有:

let x = 1.45555454;
let y = 1.45556766;

在我的情况下,它们相似,最多2位小数。因此,xy将变为1.46以进行比较。我可以格式化这些,但这肯定很慢,检查等价的最好的Rust方法是什么,所以:

if x == y { // called when we match to 2 decimal places}

进一步阐明问题并给出一些背景信息。这实际上是为了美元和美分的准确性。所以通常在python中会使用round()函数及其所有问题。是的我知道浮点表示的局限性。计算金额有两个函数,我以美元计算,需要将美分部分处理到最近的便士。

问社区的原因是我怀疑如果我自己动手,它可能会达到性能而且就是这个方面 - 这就是我为什么要使用Rust,所以我在这里。另外,我在Rust文档中看到了一些名为round()的东西,但它与pythons版本不同,它似乎采用零参数。

2 个答案:

答案 0 :(得分:7)

来自Python文档:

  

注意round()对浮点数的行为可能会令人惊讶:例如,round(2.675, 2)提供2.67而不是预期的2.68。这不是一个错误:这是因为大多数小数部分不能完全表示为浮点数。

有关详细信息,请查看What Every Programmer Should Know About Floating-Point Arithmetic

如果您不了解计算机如何处理浮点数,请不要使用此代码。如果你知道自己遇到了什么麻烦:

fn approx_equal(a: f64, b: f64, decimal_places: u8) -> bool {
    let factor = 10.0f64.powi(decimal_places as i32);
    let a = (a * factor).trunc();
    let b = (b * factor).trunc();
    a == b
}

fn main() {
    assert!( approx_equal(1.234, 1.235, 1));
    assert!( approx_equal(1.234, 1.235, 2));
    assert!(!approx_equal(1.234, 1.235, 3));
}

使用此代码已知(或可能)破坏的非详尽列表:

  • 足够大的浮点数和/或小数点数
  • 非规范化数字
  • 的NaN
  • 无穷大
  • 接近零的值(approx_equal(0.09, -0.09, 1)

一种可能的替代方案是使用定点或任意精度类型,其中任何一种都会变得更慢但在逻辑上与大多数人保持一致。

答案 1 :(得分:0)

这个似乎对我来说很好。

fn approx_equal (a:f64,b:f64,dp:u8) -> bool {
    let p:f64 = 10f64.powf(-(dp as f64));

    if (a-b).abs() < p {
        return true;
    } else {
        return false;
    }
}