Точность с плавающей точкой в ​​Clojure - PullRequest
2 голосов
/ 29 февраля 2012

Я пытаюсь выучить Clojure и попытался определить эту простую функцию:

user=> (defn triple [arg] (* 3 arg))
#'user/triple
user=> (triple 1)
3
user=> (triple 1.01)
3.0300000000000002

Может кто-нибудь объяснить, почему здесь в конце результата стоит 2?

Ответы [ 2 ]

12 голосов
/ 29 февраля 2012

Из-за представления чисел с плавающей запятой на компьютерах операции над этими числами не являются точными.Это относится как к JVM, так и к физическим машинам.См. Примеры погрешностей с плавающей запятой для более подробного обсуждения.Есть также всеобъемлющая статья Что должен знать каждый учёный об арифметике с плавающей точкой , ссылки на которые есть в ответах на этот вопрос.

6 голосов
/ 29 февраля 2012

Это связано с неточностью с плавающей запятой , которая влияет на все языки с представлениями с плавающей запятой. Есть некоторые значения, которые нельзя точно представить числами с плавающей запятой.

К счастью, Clojure также имеет поддержку высокоточных чисел, поэтому вы можете сделать:

(defn triple [arg] (* 3 arg))
(triple 1.01M)
=> 3.03M

Обратите внимание на использование «M» в конце числовых констант, чтобы указать, что вы хотите использовать высокоточные числа. В этом случае Clojure под капотом использует java.math.BigDecimal чисел.

...