重写从Python到Rust的浮点数

时间:2016-03-15 17:21:45

标签: rust rounding floating

我一直试图重写下面的代码来总结浮点数,同时最小化舍入错误,但我发现在Rust中很难做到。任何建议将不胜感激。我附上了我的非工作Rust尝试

def msum(iterable):
    "Full precision summation using multiple floats for intermediate values"
    # Rounded x+y stored in hi with the round-off stored in lo.  Together
    # hi+lo are exactly equal to x+y.  The inner loop applies hi/lo summation
    # to each partial so that the list of partial sums remains exact.
    # Depends on IEEE-754 arithmetic guarantees.  See proof of correctness at:
    #www-2.cs.cmu.edu/afs/cs/project/quake/public/papers/robust-arithmetic.ps

    partials = []               # sorted, non-overlapping partial sums
    for x in iterable:
        i = 0
        for y in partials:
            if abs(x) < abs(y):
                x, y = y, x
            hi = x + y
            lo = y - (hi - x)
            if lo:
                partials[i] = lo
                i += 1
            x = hi
        partials[i:] = [x]
    return sum(partials, 0.0)

下面的代码是我到目前为止在Rust中的代码,但它还没有工作

fn inexact_sum(v: &Vec<f64>) -> f64 {
    let mut partials: Vec<f64> = vec![];
    for x in v {

        let mut i: usize = 0;
        let mut hi: f64;
        let mut lo: f64;

        for y in partials.clone().iter() {
            hi = x + y;
            lo = if x.abs() < y.abs() {
                y - (hi - x)
            } else {
                x - (hi - y)
            };
            if lo != 0.0_f64 {
                partials[i] = lo;
                i += 1;
            }
            let x = hi;
            println!("x = {}, y = {}", x, y);
        }
        partials.truncate(i);
        partials.push(hi);
    }
    partials.iter().fold(0.0_f64, |a, b| a + b)
}

编辑:考虑一下,确实,编译器给我error: use of possibly uninitialized variable: `hi`的错误确实很有用。我应该更加关注它。关键是第一次循环根本不执行,所以hi没有初始化。因此,如果我将partials.push(hi);更改为partials.push(*x);,则代码会编译并运行,但它无法给出正确的答案。

1 个答案:

答案 0 :(得分:4)

这是你在找什么?我认为你并不是要克隆partials数组,而是发现你需要为了满足借用检查器;如果您尝试使用代码:

for y in partials.iter() {
    ...
    partials[i] = lo;

借款检查员会抱怨:

<anon>:13:17: 13:25 error: cannot borrow `partials` as mutable because it is also borrowed as immutable [E0502]

我通过在数组中使用索引来解决这个问题:

for j in 0..partials.len() {
    let mut y = partials[j];

然后你不是每次都围绕外循环克隆整个部分数组!由于partials数组可以在迭代时进行修改,因此首先使用克隆意味着如果已经修改了y而不是新值,那么最终将使用旧值{。}}。

use std::mem;

fn msum(v: &[f64]) -> f64 {
    let mut partials: Vec<f64> = vec![];
    for x in v {
        let mut x = *x;
        let mut i = 0;
        for j in 0..partials.len() {
            let mut y = partials[j];
            if x.abs() < y.abs() { mem::swap(&mut x, &mut y) }
            let hi = x + y;
            let lo = y - (hi - x);
            if lo != 0.0 {
                partials[i] = lo;
                i += 1;
            }
            x = hi;
        }
        partials.truncate(i);
        partials.push(x);
    }
    partials.iter().fold(0., |a, b| a + b)
}

fn main() {
    let v = vec![1.234, 1e16, 1.234, -1e16];
    println!("{}",msum(&v));
}

Playpen