如何做一个浮点数的二进制search?
如果你有一个Vec<u32>
你可以使用slice::binary_search
方法。
由于我不明白的原因, f32
和f64
不执行Ord
。 由于原始types来自标准库,所以你Ord
实现Ord
,所以不会出现你可以使用这个方法。
你怎么能有效地做到这一点?
我真的必须在包装结构中包装f64
并实现Ord
吗? 要做到这一点似乎是非常痛苦的,并且涉及到大量的transmute
,无意中无意地来回传递大量数据。
由于我不明白的原因,f32和f64不实现Ord。
因为浮点很难 ! 简短的版本是浮点数有一个特殊的值NaN – 不是一个数字。 IEEE浮点数规范指出1 < NaN
, 1 > NaN
和NaN == NaN
都是false
。
Ord
说:
构成总订单的types的特质。
这意味着比较需要有整体性 :
a≤b或b≤a
但是我们只是看到浮点没有这个属性。
所以是的,你将需要创build一个包装types,以某种方式处理比较大量的NaN值 。 也许你的情况下,你可以断言,浮动值是从来没有NaN,然后调用到正常的PartialOrd
特质。 这是一个例子:
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); }
其中一个切片方法是binary_search_by
,您可以使用它。 f32
/ f64
实现PartialOrd
,所以如果你知道他们永远不可能是NaN
,你可以解开partial_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), } }