2011-08-02 14 views

Odpowiedz

43

Jest to ogólna zasada, jak 64-bitowych liczb zmiennoprzecinkowych są porównywane według IEEE 754 (nie Scali czy nawet Java związanych patrz NaN):

double n1 = Double.NaN; 
double n2 = Double.NaN; 
System.out.println(n1 == n2);  //false 

Pomysł jest to, że NaN jest wartością znacznika dla nieznanego lub nieokreślonego. Porównywanie dwóch nieznanych wartości zawsze powinno dać false, ponieważ są one dobrze ... nieznane.


Jeśli chcesz użyć wzór pasujący z NaN, spróbuj tego:

myDouble match { 
    case x if x.isNaN => ... 
    case _ => ... 
} 

Ale myślę, pasujące do wzorca użyje ścisłe podwójne porównania więc należy być ostrożnym z tego konstruktu.

+0

+1 za wskazanie, że 'NaN = NaN' w wielu (jeśli nie wszystkich) języków programowania, które narażają tym! wartość dla programisty. –

+1

Należy zauważyć, że jeśli większość liczb nie jest NaN, '.isNaN' jest tylko o połowę szybsza od' java.lang.Double.isNaN', więc ta ostatnia powinna być preferowana w ciasnych pętlach. (Dopasowanie jest tak szybkie, jak instrukcja if.) Dla jasności (tj. Wszędzie z wyjątkiem ciasnych pętli krytycznych pod względem wydajności), forma '.isNaN' jest prawdopodobnie najlepsza. –

4

Tomasz ma rację. Zamiast tego należy użyć isNaN.

scala> Double.NaN.isNaN 
res0: Boolean = true 
11

Można napisać ściągacza (zaktualizowane zgodnie z komentarzem za BSE):

object NaN { 
    def unapply(d:Double) = d.isNaN 
} 


0.0/0.0 match { 
    case NaN() => println("NaN") 
    case x => println("boring " + x) 
} 
//--> NaN 
+2

Ekstraktor może być jeszcze prostszy: 'object NaN {def unapply (d: Double) = d.isNaN}'. Może być używany w następujący sposób: '0.0/0.0 mecz {case NaN() => print (" NaN ")}' – bseibold

+0

@bse: Dzięki, zaktualizowałem swoją odpowiedź. – Landei