Точность с плавающей точкой в Clojure
Я пытаюсь изучить Clojure и попытался определить эту простую функцию:
user=> (defn triple [arg] (* 3 arg))
#'user/triple
user=> (triple 1)
3
user=> (triple 1.01)
3.0300000000000002
Кто-нибудь может объяснить, почему здесь стоит 2 в конце результата?
2 ответа
Из-за представления чисел с плавающей запятой на компьютерах операции над этими числами не являются точными. Это относится как к JVM, так и к физическим машинам. См. Примеры погрешностей с плавающей точкой для более подробного обсуждения. В ответах на этот вопрос есть также всеобъемлющая статья " Что должен знать каждый компьютерщик" об арифметике с плавающей точкой.
Это связано с неточностью с плавающей запятой, которая влияет на все языки с представлениями с плавающей запятой. Есть некоторые значения, которые нельзя точно представить числами с плавающей запятой.
К счастью, Clojure также имеет поддержку высокоточных чисел, поэтому вы можете сделать:
(defn triple [arg] (* 3 arg))
(triple 1.01M)
=> 3.03M
Обратите внимание на использование "M" в конце числовых констант, чтобы указать, что вы хотите использовать высокоточные числа. В этом случае числа java.math.BigDecimal используются Clojure под капотом.