If you have a Vec<u32>
you would use the slice::binary_search
method.
For reasons I don't understand, f32
and f64
do not implement Ord
. Since the primitive types are from the standard library, you cannot implement Ord
on them yourself, so it does not appear you can use this method.
How can you effectively do this?
Do I really have to wrap f64
in a wrapper struct and implement Ord
on it? It seems extremely painful to have to do this, and involves a great deal of transmute
to cast blocks of data back and forth unsafely for effectively no reason.
One of the slice methods is
binary_search_by
, which you could use.f32
/f64
implementPartialOrd
, so if you know they can never beNaN
, you can unwrap the result ofpartial_cmp
:https://github.com/emerentius/ord_subset implements a
ord_subset_binary_search()
method that you can use for this.from their README:
Because floating point is hard! The short version is that floating point numbers have a special value NaN - Not a Number. The IEEE spec for floating point numbers states that
1 < NaN
,1 > NaN
, andNaN == NaN
are allfalse
.Ord
says:This means that the comparisons need to have totality:
but we just saw that floating points do not have this property.
So yes, you will need to create a wrapper type that somehow deals with comparing the large number of NaN values. Maybe your case you can just assert that the float value is never NaN and then call out to the regular
PartialOrd
trait. Here's an example:If you are sure that your floating point values will never be NaN, you can express this semantic with the wrappers in decorum. Specifically, the type
Ordered
implementsOrd
and panics whenever the program tries to do something invalid: