16

I have a test of division, where I sometimes need to check that my results are either NaN or inf, but it seems like Rust does not consider NaN to be equal to NaN:

fn main() {
    let nan = "NaN".parse::<f64>().unwrap();
    println!("{:?}", nan);
    println!("{:?}", nan == nan);
} // NaN false

How do I compare two vectors that contain NaN and infinity to see whether they are equal?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
The Unfun Cat
  • 29,987
  • 31
  • 114
  • 156
  • 1
    What do you want the result to be if there are NaN/inf? – Chris Emerson Nov 23 '16 at 15:04
  • 2
    FYI, there's a [`NAN` constant](https://doc.rust-lang.org/std/f64/constant.NAN.html); you don't need to involve parsing. – Shepmaster Nov 23 '16 at 15:14
  • Potentially relevant information is available in http://stackoverflow.com/q/39638363/155423; http://stackoverflow.com/q/26489701/155423; http://stackoverflow.com/q/28247990/155423. – Shepmaster Nov 23 '16 at 15:36

2 Answers2

14

NaNs by definition compare unequal. If you want to do something different you've got to define the comparison by yourself. It's not too difficult; the iterator methods do most of the work for you:

fn eq_with_nan_eq(a: f64, b: f64) -> bool {
    (a.is_nan() && b.is_nan()) || (a == b)
}

fn vec_compare(va: &[f64], vb: &[f64]) -> bool {
    (va.len() == vb.len()) &&  // zip stops at the shortest
     va.iter()
       .zip(vb)
       .all(|(a,b)| eq_with_nan_eq(*a,*b))
}

fn main() {
    use std::f64::NAN;
    let a = vec![0f64, 1.0, NAN];
    let b = vec![0f64, 2.0, NAN];
    let c = vec![0f64, 1.0, NAN, 4.0];
    let d = vec![0f64, 1.0, 3.0];

    assert_eq!(vec_compare(&a, &b), false);
    assert_eq!(vec_compare(&a, &a), true);
    assert_eq!(vec_compare(&a, &d), false);
    assert_eq!(vec_compare(&a, &c), false);
}

Playground

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Chris Emerson
  • 13,041
  • 3
  • 44
  • 66
7

You might be interested in the is_nan method.

assert!(nan.is_nan());
Matthieu M.
  • 287,565
  • 48
  • 449
  • 722