我一直试图重写下面的代码来总结浮点数,同时最小化舍入错误,但我发现在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);
,则代码会编译并运行,但它无法给出正确的答案。
答案 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));
}