Jux*_*hin 4 algorithm floating-point idiomatic rust
假设 -该Vec<f32>不会不具有任何NaN价值或表现出任何NaN行为.
采取以下样本集:
0.28
0.3102
0.9856
0.3679
0.3697
0.46
0.4311
0.9781
0.9891
0.5052
0.9173
0.932
0.8365
0.5822
0.9981
0.9977
Run Code Online (Sandbox Code Playgroud)
获取上述列表中最高值索引的最新且最稳定的方法是什么(值可以是负数)?
我最初的尝试大致如下:
let _tmp = *nets.iter().max_by(|i, j| i.partial_cmp(j).unwrap()).unwrap();
let _i = nets.iter().position(|&element| element == _tmp).unwrap();
Run Code Online (Sandbox Code Playgroud)
哪里nets是&Vec<f32>.对我来说,这显然是不正确的.
相当于Python的Python(考虑到上面的假设):
_i = nets.index(max(nets))
Run Code Online (Sandbox Code Playgroud)
我可能会做这样的事情:
fn main() -> Result<(), Box<std::error::Error>> {
let samples = vec![
0.28, 0.3102, 0.9856, 0.3679, 0.3697, 0.46, 0.4311, 0.9781, 0.9891, 0.5052, 0.9173, 0.932,
0.8365, 0.5822, 0.9981, 0.9977,
];
// Use enumerate to get the index
let mut iter = samples.iter().enumerate();
// we get the first entry
let init = iter.next().ok_or("Need at least one input")?;
// we process the rest
let result = iter.try_fold(init, |acc, x| {
// return None if x is NaN
let cmp = x.1.partial_cmp(acc.1)?;
// if x is greater the acc
let max = if let std::cmp::Ordering::Greater = cmp {
x
} else {
acc
};
Some(max)
});
println!("{:?}", result);
Ok(())
}
Run Code Online (Sandbox Code Playgroud)
这可以通过在 Iterator 上添加一个 trait 来实现,例如 function try_max_by。
有什么理由为什么这行不通?
use std::cmp::Ordering;
fn example(nets: &Vec<f32>) {
let index_of_max: Option<usize> = nets
.iter()
.enumerate()
.max_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap_or(Ordering::Equal))
.map(|(index, _)| index);
}
Run Code Online (Sandbox Code Playgroud)
您可以通过以下方式找到最大值:
let mut max_value = my_vec.iter().fold(0.0f32, |max, &val| if val > max{ val } else{ max });
Run Code Online (Sandbox Code Playgroud)
找到后,max_value您可以跟踪它在矢量本身中的位置:
let index = my_vec.iter().position(|&r| r == max_value).unwrap();
Run Code Online (Sandbox Code Playgroud)
为了得到这个结果,你需要在同一个向量上迭代两次。为了提高性能,您可以在fold迭代中将具有最大值的索引值作为元组返回。
这很棘手的原因是因为f32没有实现Ord.这是因为NaN值会阻止浮点数形成总订单,这违反了合同Ord.
通过定义一个不允许包含a的数字类型包装,可以解决这个问题NaN.一个例子是有序浮动.如果您使用此包来首先准备集合以包含NotNan值,那么您可以编写非常接近原始想法的代码:
use ordered_float::NotNan;
let non_nan_floats: Vec<_> = nets.iter()
.cloned()
.map(NotNan::new) // Attempt to convert each f32 to a NotNan
.filter_map(Result::ok) // Unwrap the `NotNan`s and filter out the `NaN` values
.collect();
let max = non_nan_floats.iter().max().unwrap();
let index = non_nan_floats.iter().position(|element| element == max).unwrap();
Run Code Online (Sandbox Code Playgroud)
将此添加到Cargo.toml:
[dependencies]
ordered-float = "1.0.1"
Run Code Online (Sandbox Code Playgroud)
额外材料:通过利用具有透明表示的事实,类型转换可以真正实现零成本(假设您确实没有NaN值!)NotNan
let non_nan_floats: Vec<NotNan<f32>> = unsafe { mem::transmute(nets) };
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2113 次 |
| 最近记录: |