Rust 如何对浮点向量进行二进制搜索?

Rust 如何对浮点向量进行二进制搜索?,rust,Rust,如果您有一个Vec,您将使用该方法 出于我不理解的原因,f32和f64没有实现Ord。由于基元类型来自标准库,因此您不能自己在基元类型上实现Ord,因此您似乎无法使用此方法 如何有效地做到这一点 我真的必须在包装器结构中包装f64,并在其上实现Ord?必须这样做似乎非常痛苦,需要大量的transmute来无理由地不安全地来回转换数据块 出于我不理解的原因,f32和f64没有实现Ord 因为!简短的版本是浮点数有一个特殊的值NaN,而不是一个数字。IEEE浮点数规范规定1NaN和NaN==NaN均

如果您有一个
Vec
,您将使用该方法

出于我不理解的原因,
f32
f64
没有实现
Ord
。由于基元类型来自标准库,因此您不能自己在基元类型上实现
Ord
,因此您似乎无法使用此方法

如何有效地做到这一点

我真的必须在包装器结构中包装
f64
,并在其上实现
Ord
?必须这样做似乎非常痛苦,需要大量的
transmute
来无理由地不安全地来回转换数据块

出于我不理解的原因,f32和f64没有实现Ord

因为!简短的版本是浮点数有一个特殊的值NaN,而不是一个数字。IEEE浮点数规范规定
1
1>NaN
NaN==NaN
均为
false

说:

构成一个整体的类型的特征

这意味着比较需要具有总体性:

a≤ b或b≤ a

但是我们刚刚看到浮点没有这个属性

因此,是的,您将需要创建一个包装器类型,以某种方式处理比较。也许在你的情况下,你可以断言浮点值永远不是NaN,然后调用常规特征。下面是一个例子:

use std::cmp::Ordering;

#[derive(PartialEq,PartialOrd)]
struct NonNan(f64);

impl NonNan {
    fn new(val: f64) -> Option<NonNan> {
        if val.is_nan() {
            None
        } else {
            Some(NonNan(val))
        }
    }
}

impl Eq for NonNan {}

impl Ord for NonNan {
    fn cmp(&self, other: &NonNan) -> Ordering {
        self.partial_cmp(other).unwrap()
    }
}

fn main() {
    let mut v: Vec<_> = [2.0, 1.0, 3.0].iter().map(|v| NonNan::new(*v).unwrap()).collect();
    v.sort();
    let r = v.binary_search(&NonNan::new(2.0).unwrap());
    println!("{:?}", r);
}
使用std::cmp::排序;
#[推导(PartialEq,PartialOrd)]
结构NonNan(f64);
impl NonNan{
fn新(val:f64)->选项{
如果val.is_nan(){
没有一个
}否则{
一些(非南(瓦尔))
}
}
}
非NaN{}的impl Eq
为NonNan请求{
fn cmp(&self,其他:&NonNan)->订购{
self.partial_cmp(其他).unwrap()
}
}
fn main(){
让mut v:Vec=[2.0,1.0,3.0].iter().map(|v | NonNan::new(*v).unwrap()).collect();
v、 排序();
让r=v.binary_搜索(&NonNan::new(2.0).unwrap());
println!(“{:?}”,r);
}

切片方法之一是,您可以使用
f32
/
f64
执行
PartialOrd
,因此,如果您知道它们可以永不成为
NaN
,您可以打开
部分cmp
的结果:

fn main() {
    let values = [1.0, 2.0, 3.0, 4.0, 5.0];
    let location = values.binary_search_by(|v| {
        v.partial_cmp(&3.14).expect("Couldn't compare values")
    });

    match location {
        Ok(i) => println!("Found at {}", i),
        Err(i) => println!("Not found, could be inserted at {}", i),
    }
}
实现可用于此操作的
ord\u subset\u binary\u search()
方法

从他们的自述:

let mut s = [5.0, std::f64::NAN, 3.0, 2.0];
s.ord_subset_sort();
assert_eq!(&s[0..3], &[2.0, 3.0, 5.0]);
assert_eq!(s.ord_subset_binary_search(&5.0), Ok(2));

assert_eq!(s.iter().ord_subset_max(), Some(&5.0));
assert_eq!(s.iter().ord_subset_min(), Some(&2.0));

如果您确信您的浮点值永远不会是NaN,那么您可以使用中的包装器来表达这种语义。具体来说,该类型实现了
Ord
,并且每当程序尝试执行无效操作时,该类型就会崩溃:

use decorum::Ordered;

fn foo() {
    let ordered = Ordered<f32>::from_inner(10.);
    let normal = ordered.into()
}
使用礼仪::有序;
fn foo(){
let ordered=ordered::from_inner(10.);
让normal=ordered.into()
}

切片扩展方法之一是
二进制搜索方法,您可以使用它
f32
/
f64
实现
PartialOrd
,因此如果您知道它们永远不会是
NaN
,您可以打开
partial\u cmp
的结果:可以使用或板条箱。看见