Reputation: 47
My tests fail when using floating point numbers f64
due to precision errors.
use std::ops::Sub;
#[derive(Debug, PartialEq, Clone, Copy)]
struct Audio {
amp: f64,
}
impl Sub for Audio {
type Output = Self;
fn sub(self, other: Self) -> Self::Output {
Self {
amp: self.amp - other.amp,
}
}
}
#[test]
fn subtract_audio() {
let audio1 = Audio { amp: 0.9 };
let audio2 = Audio { amp: 0.3 };
assert_eq!(audio1 - audio2, Audio { amp: 0.6 });
assert_ne!(audio1 - audio2, Audio { amp: 1.2 });
assert_ne!(audio1 - audio2, Audio { amp: 0.3 });
}
I get the following error:
---- subtract_audio stdout ----
thread 'subtract_audio' panicked at 'assertion failed: `(left == right)`
left: `Audio { amp: 0.6000000000000001 }`,
right: `Audio { amp: 0.6 }`', src/lib.rs:23:5
How to test for structs with floating numbers like f64
?
Upvotes: 0
Views: 2322
Reputation: 47
If the comparing were to be done with numbers without struct,
let a: f64 = 0.9;
let b: f64 = 0.6;
assert!(a - b < f64:EPSILON);
But with structs we need to take extra measures.
First need to derive with PartialOrd
to allow comparing with other structs.
#[derive(Debug, PartialEq, PartialOrd)]
struct Audio {...}
next create a struct for comparison
let audio_epsilon = Audio { amp: f64:EPSILON };
now I can compare regularly (with assert!
not assert_eq!
)
assert!(c - d < audio_epsilon)
An other solution is to implement PartialEq
manually:
impl PartialEq for Audio {
fn eq(&self, other: &Self) -> bool {
(self.amp - other.amp).abs() < f64::EPSILON
}
}
Upvotes: 3