2012-02-29 5 views
2

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

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

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

+0

Вы можете прочитать некоторые анализы по проблеме здесь: http://stackoverflow.com/questions/9136860/how-to-check-dependencies-of-floats/9136907#9136907 – Gangnus

+0

Обратите внимание, что это не специфический для clojure но один из того, как компьютеры обрабатывают арифметику в целом. –

ответ

12

Из-за представления чисел с плавающей запятой на компьютерах операции с этими числами неточны. Он применяется как к JVM, так и к физическим машинам. См. Floating point inaccuracy examples для более продолжительного обсуждения. В ответах на этот вопрос также содержится исчерпывающая статья What Every Computer Scientist Should Know About Floating-Point Arithmetic.

6

Это связано с floating point inaccuracy, которое затрагивает все языки с представлениями с плавающей точкой. Существуют некоторые значения, которые не могут быть точно представлены с номерами с плавающей запятой.

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

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

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

+1

Фактически, когда вы используете обозначение M, вы получаете не только высокую точность, но и произвольную точность. Это не просто переход от 32 бит до 64 бит. – user100464

+1

Просто для полноты, он также работает с отношениями, например. (тройной (/ 101 100)) => 303/100 – status203

Смежные вопросы