【问题标题】:How to deal with inexact floating point arithmetic results in Rust? [closed]如何处理 Rust 中不精确的浮点运算结果? [关闭]
【发布时间】:2018-10-25 22:24:38
【问题描述】:

Rust 中如何处理浮点运算?

For example:

fn main() {
    let vector = vec![1.01_f64, 1.02, 1.03, 1.01, 1.05];

    let difference: Vec<f64> = vector.windows(2).map(|slice| slice[0] - slice[1]).collect();
    println!("{:?}", difference);
}

返回:

[-0.010000000000000009, -0.010000000000000009, 0.020000000000000018, -0.040000000000000036]

预期输出:

[-0.01, -0.01, 0.02, -0.04]

我了解发生这种情况的原因,但从未解决它。

更新:

发表这篇文章是因为 Python 等其他语言的结果似乎是准确的。该计划是在 Rust 中复制 Python 的方法,但经过进一步调查,Python、numpy 和 pandas 都以相同的方式处理数字。也就是说,不准确性仍然存在,但并不总是可见/显示。另一方面,Rust 使这些不准确之处显而易见,起初令人困惑。

例子:

l = [1.01, 1.02, 1.03, 1.01, 1.05]

for i in l:
    print('%.18f' % i)

打印:

1.010000000000000009
1.020000000000000018
1.030000000000000027
1.010000000000000009
1.050000000000000044

print(l) 打印:

[1.01, 1.02, 1.03, 1.01, 1.05]

【问题讨论】:

标签: floating-point rust precision floating-accuracy


【解决方案1】:

既然你知道为什么会这样,我假设你想格式化输出。

official docs

精度

对于非数字类型,这可以被认为是“最大宽度”。如果生成的字符串长于此宽度,则将其截断为这么多字符,并且如果设置了这些参数,则使用正确的fillalignmentwidth 发出截断值。

对于整数类型,这将被忽略。

对于浮点类型,这表示应该打印小数点后的位数。

有三种可能的方式来指定所需的precision

  1. 一个整数.N

    整数N 本身就是精度。

  2. 一个整数或名称后跟美元符号.N$

    使用格式参数N(必须是usize)作为精度。

  3. 星号.*:

    .* 表示此{...}两个 格式输入相关联,而不是一个:第一个输入保存usize 精度,第二个保存要打印的值。请注意,在这种情况下,如果使用格式字符串{&lt;arg&gt;:&lt;spec&gt;.*},则&lt;arg&gt; 部分指的是要打印的值,precision 必须出现在&lt;arg&gt; 之前的输入中。

所以在你的情况下,其中一个可以完成这项工作:

println!("{0:.2?}", difference);
println!("{1:.0$?}", 2, difference);
println!("{:.*?}", 2, difference);
println!("{1:.*?}", 2, difference);
println!("{number:.prec$?}", prec = 2, number = difference);

Playground

但是,如果您想继续保持这种精度,您可以对结果进行四舍五入:

.map(|x| (x * 100.0).round() / 100.0)

Playground


另见:

【讨论】:

    猜你喜欢
    • 2016-11-22
    • 1970-01-01
    • 2019-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-19
    • 1970-01-01
    • 2018-08-12
    相关资源
    最近更新 更多