2015-02-02 6 views
10

Ich bin in Clojure-Verhältnis verloren. Ich kann es nicht verstehen. Warum verhalten sich die Gleichheits- und Ungleichheitstests so?warum clojure clojure.lang.Ratio 3/2 nicht = 1.5

(= 3/2 1.5) 
;; false 
(>= 3/2 1.5) 
;; true 
(> 3/2 1.5) 
;;false 
(not= 3/2 1.5) 
;; true 
+0

Diese Frage ist kein Duplikat von: http://stackoverflow.com/questions/2364566/and-in-clojure?rq=1 weil die Sprache geändert wurde, seit diese Frage gestellt wurde, so dass die Beispiele in dieser Frage festgelegt sind Antwort funktioniert nicht. Es stellt auch die Frage aus einem anderen Kontext –

+0

Übrigens ist dies nicht für Verhältnisse spezifisch. '(= 1 1.0)' gibt 'false' zurück. – Thumbnail

Antwort

12

Verwenden == für numerische Vergleiche, wo Sie wollen wissen, ob zwei Zahlen die gleiche Anzahl unabhängig von Typen darstellen:

user> (= 3/2 1.5) 
false 
user> (== 3/2 1.5) 
true 

Obwohl im Auge behalten, dass ==für Zahlen nur und wirft wenn gab etwas nicht eine Nummer.

user> (== :1 :1) 
ClassCastException clojure.lang.Keyword cannot be cast to java.lang.Number clojure.lang.Numbers.equiv (Numbers.java:206) 
+1

Wie Ihre Antwort zeigt, löst '(==: 1: 1)' eine Ausnahme aus. Es kehrt nicht wie bisher falsch zurück oder irgendetwas anderes. – Thumbnail

+0

Tut mir leid, vergessen, meine Antwort nach dem Testen zu bearbeiten und das Beispiel hinzuzufügen. –

2

Clojure versucht hart Sie weg von Schwimmern zu halten, da sie zu Rundungsfehler anfällig sind:

user=> (+ 0.1 0.2) 
0.30000000000000004 
user=> 

So ist der wahre Grund ist der Vergleich nicht, dass es keine genaue Weg ist 1,5 intern darzustellen, und der Moment, in dem der Clojure-Parser "1.5" verbraucht, ist möglicherweise verloren.

von Fraktionen mit, gibt es keinen Informationsverlust, so 3/2 die Fraktion Form frei um ohne Angst vor außer Kontrolle geratener Rundungsfehler an anderen Funktionen übergeben werden kann as was the case with the infamous Patriot missile bug.

+2

Hmm. Unter der Annahme, dass Clojure IEEE 754 binary64 floats (wie Java und so ziemlich jede andere Mainstream-Sprache) verwendet, kann "1.5" absolut * genau dargestellt werden, da es in binärer Sprache als '1.1' perfekt ausgedrückt werden kann. "1.4" wäre natürlich eine andere Sache ... –

+1

okay, die richtige Formulierung wäre dann _ "jedes Mal, wenn Clojure einen Float konsumiert, könnten Informationen verloren gehen ..." _ – ekarak

1

Einfach ausgedrückt, in Clojure Verhältnis ein Typ ist. Es wird nicht versucht, es in Double oder Float zu konvertieren. Auf diese Weise können Sie bewahren, was die Zahl tatsächlich darstellt, ohne Genauigkeit zu verlieren.

Check-out Rich Hickey's Vortrag namens "Clojure für Java-Programmierer" in YouTube, Er erklärt es besser.

Verwandte Themen