Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 686
bluenote10 Avatar asked Nov 16 '14 14:11

bluenote10


1 Answers

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.

like image 148
Dan Simon Avatar answered Sep 21 '22 19:09

Dan Simon