如何计算值向量差的最小值?

时间:2018-05-15 06:57:24

标签: vector rust

如何计算Rust中矢量的最小差异?

以下代码:

fn main() {
    let vector: Vec<f64> = vec![1.025, 1.028, 1.03, 1.05, 1.051];

    let mut result: Vec<f64> = Vec::new();
    for i in 0..vector.len() - 1 {
        result.push(vector[i] - vector[i + 1]);
    }
    println!("{:?}", result);

    let minimum = std::cmp::min(&result[0], &result[1]);
    println!("{}", minimum)
}

结果:

error[E0277]: the trait bound `f64: std::cmp::Ord` is not satisfied
  --> src/main.rs:10:19
   |
10 |     let minimum = std::cmp::min(&result[0], &result[1]);
   |                   ^^^^^^^^^^^^^ the trait `std::cmp::Ord` is not implemented for `f64`
   |
   = note: required because of the requirements on the impl of `std::cmp::Ord` for `&f64`
   = note: required by `std::cmp::min`

挑战是:

  • no comparison between f32/f64 types

  • 任何时候都只能比较两个值;我该如何计算所有值?可以使用折叠还是必须是宏?

  • 在向量上执行差异的内存有效方法是什么?例如,创建一个范围并迭代一个向量(for i in 0..5 { vector[i] })比在向量本身for i in &vector上创建一个迭代器更加昂贵。

2 个答案:

答案 0 :(得分:9)

使用迭代器!

在切片上,可以使用windows()方法获取连续的元素对。在您的情况下,<div class="box"> <div class="frm"> <center><h2>Simple Form</h2></center> <div class="line"> <label for="name">Enter Your Name</label> <input type="text" id="name"> </div> <div class="line"> <label for="email">Enter Your Email</label> <input type="text" id="email"> </div> <div class="line"> <label for="pass">Enter Your Password</label> <input type="text" id="pass"> </div> </div> </div>将产生:vector.windows(2)[1.025, 1.028][1.028, 1.03],最后[1.03, 1.05]

这是一个迭代器,因此您可以对其应用转换。在您的情况下,我建议map,将每对映射到对中两个元素之间的差异:[1.05, 1.051]。并且可以使用.map(|slice| slice[0] - slice[1])来获取绝对差异。

这仍然是一个迭代器,所以最后你可以应用min_by,它只会产生所有元素的最小值。浮动只实现(slice[0] - slice[1]).abs() 1 ,因此:PartialOrd

完全放在in the playground

.min_by(|x, y| x.partial_cmp(y).unwrap())

1 如此处所示,可以比较浮点数。然而,由于存在NaN,结果为fn main() { let vector = vec![1.025_f64, 1.028, 1.03, 1.05, 1.051]; let minimum = vector.windows(2) .map(|slice| (slice[0] - slice[1]).abs()) .min_by(|x, y| x.partial_cmp(y).unwrap()); println!("{:?}", minimum); } 。在这种情况下,假设输入数据中没有NaN,我只使用Option<Ordering>来获取基础排序;如果一个NaN潜入,它会恐慌。

答案 1 :(得分:2)

你可以这样做:

let v = vec![1.025f64, 1.028, 1.03, 1.05, 1.051];
let min = (0..v.len() - 1)
    .map(|i| (v[i] - v[i + 1]).abs())
    .min_by(|a, b| a.partial_cmp(b).unwrap());  // panic on `NaN`

println!("{:?}", min);

此代码不使用临时向量来保存差异。相反,由于懒惰的迭代器,它可以动态计算所有内容。另请注意,我使用abs()来计算绝对差异(这可能是您想要的)。

要查找最低要求,Iterator会提供一系列方法:min()min_by_keymin_by。我用后者来处理无法比较浮动的问题。如果我们遇到NaN值,我的代码就会引起恐慌。这可能适用于您的用例,但您可能期望NaN值,并希望处理错误。

结果min变量是Option<f64>,如果向量的长度为1,则为None。如果向量的长度为0,则在索引v[i + 1]时会发生混乱。< / p>

关于你的“花车不准确”问题:是的,这是真的。真正解决此问题的唯一方法是使用任意精度类型。可能有几个箱子提供这种类型。但这不再是这个问题的范围了。