If I have a couple of floating-point numbers and try to sort them like this:
fn main() {
let mut nums: Vec<f64> = vec![0.53, 3.18, 4.783, 9.0, -1.2, 0.0];
nums.sort();
println!("{:?}", nums);
}
I get a compile error: "the trait bound f64: Ord
is not satisfied".
How can I sort these numbers?
TLDR: do
nums.sort_by(f64::total_cmp);
The basic reason why Rust doesn't let you sort floating-point numbers is that NaN
is weird. All comparisons involving a NaN
return false
, which can cause sorting algorithms to break (this is an issue in Python, for example). There's also the strange case of zero and negative zero, which are equal yet have different representations. Since Rust's design philosophy revolves around handling errors explicitly, you cannot use the sort()
method on floats.
However, IEEE 754 does define a way to sort floating-point numbers which can handle any kind of NaN
(there are many bit patterns which represent a NaN
). The order is:
NaN
(negative sign bit), in descending order of the significand bitsNaN
(positive sign bit), in ascending order of the significand bitsTo get this ordering, Rust offers the total_cmp method between all the float types. Therefore, your code can be fixed by doing:
fn main() {
let mut nums: Vec<f64> = vec![0.53, 3.18, 4.783, 9.0, -1.2, 0.0];
nums.sort_by(f64::total_cmp);
println!("{:?}", nums);
}
Addendum
There are two alternatives that might be better for certain use cases:
nums.sort_unstable_by(f64::total_cmp);
sort_unstable_by
uses a different sorting algorithm that is likely faster than the standard one, but you should benchmark your application to make sure (relevant issue).
#![feature(sort_floats)] // requires nightly toolchain
nums.sort_floats();
sort_floats
is the same as the above but has not yet been stabilized.