bluenote10
bluenote10

Reputation: 26560

How do I automatically implement comparison for structs with floats in Rust?

I'm trying to automatically "derive" comparison functionality for a simple struct like this:

#[derive(PartialEq, Eq)]
struct Vec3 {
    x: f64,
    y: f64,
    z: f64,
}

However, Rust 1.15.1 complains:

error[E0277]: the trait bound `f64: std::cmp::Eq` is not satisfied
 --> src/main.rs:3:5
  |
3 |     x: f64,
  |     ^^^^^^ the trait `std::cmp::Eq` is not implemented for `f64`
  |
  = note: required by `std::cmp::AssertParamIsEq`

What exactly am I supposed to do to allow the derivation of a default implementation here?

Upvotes: 30

Views: 20741

Answers (1)

Dan Simon
Dan Simon

Reputation: 13137

Rust intentionally does not implement Eq for float types. This reddit discussion may shed some more light on why, but the tl;dr is that floating point numbers aren't totally orderable so bizarre edge cases are unavoidable.

However, if you want to add comparison to your struct, you can derive PartialOrd instead. This will give you implementations of the comparative and equality operators:

#[derive(PartialEq, PartialOrd)]
struct Vec3 {
    x: f64,
    y: f64,
    z: f64,
}

fn main() {
    let a = Vec3 { x: 1.0, y: 1.1, z: 1.0 };
    let b = Vec3 { x: 2.0, y: 2.0, z: 2.0 };

    println!("{}", a < b); //true
    println!("{}", a <= b); //true
    println!("{}", a == b); //false
}

The difference between Eq and PartialEq (and hence between Ord and PartialOrd) is that Eq requires that the == operator form an equivalence relation, whereas PartialOrd only requires that == and != are inverses. So just as with floats themselves, you should keep that in mind when doing comparisons on instances of your struct.

Upvotes: 43

Related Questions