Почему clojure clojure.lang.Ratio 3/2 not = 1.5

Я потерялся в соотношении clojure. Я не могу этого понять. Почему тесты равенства и неравенства ведут себя таким образом?

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

Ответ 1

Используйте == для численных сравнений, где вы хотите узнать, представляют ли два числа одинаковое число независимо от типов:

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

Хотя имейте в виду, что == есть только для чисел и бросает, если задано что-то не число.

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

Ответ 2

Clojure пытается удержать вас от поплавков, поскольку они подвержены ошибкам округления:

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

Таким образом, истинная причина неудачи сравнения заключается в том, что нет точного способа представления 1.5 внутри, и момента, когда парсер Clojure потребляет информацию "1.5", потенциально теряется.

Используя фракции, нет потери информации, поэтому форма 3/2 может быть свободно передана другим функциям, не опасаясь ошибок округления округления as был случай с печально известной ракетной ошибкой Patriot.

Ответ 3

Проще говоря, в Clojure отношение - это тип. Он не пытается преобразовать его в double или float или что-нибудь в этом роде. Таким образом, вы можете сохранить то, что фактически представляет количество, не теряя при этом никакой точности.

Выписка Rich Rich Hickey под названием "Clojure для Java-программистов" на YouTube, он объясняет это лучше.