Точность с плавающей точкой в ​​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 под капотом.

Другие вопросы по тегам