Какова философия использования значений с плавающей запятой в Clojure?

В настоящее время я работаю с Clojure-on-top-of-the-JVM.

язык Java, раскрывающий функциональность JVM с плавающей запятой, говорит, что мы получаем (точно) IEEE-754 32-битная одинарная точность (Java "плавающая") и 64-битные представления двойной точности (Java "double") и что JVM может использовать "расширенная точность" реализация (80 бит для «расширенного двойного», также известного как «длинный двойной» в некоторых языках программирования) во время вычисления. Пока ни слова о половинной или четверной точности.

Для Clojure-on-top-of-ECMAScript (т. е. ClojureScript) существует единственный базовый числовой тип, который является 64-битным с плавающей запятой двойной точности IEEE-754.

Кажется, что в случае Clojure-on-the-JVM использование «двойного» поощряется во всех случаях, когда ожидаются числа с плавающей запятой. Нет даже способа проверить, является ли данная вещь числом с плавающей запятой одинарной точности, поскольку float? (возможно, неожиданно) проверяет, является ли вещь каким-либо значением с плавающей запятой. Как ни странно, существует функция «преобразования в число с плавающей запятой», называемая float.

(defn whatf [x] [(double? x) (float? x) (type x)])

; a literal containing a decimal point is mapped to a 
; "Java double" (boxed)

(whatf 0.1)
;=> [true true java.lang.Double]

; an integer is a "Java long" (boxed), as expected:

(whatf 1)
;=> [false false java.lang.Long]

; you can cast to "float", which corresponds to "Java float".
; and "double?" returns false for that:

(whatf (float 1))
;=> [false true java.lang.Float]

; you can cast to "double":

(whatf (double 1))
;=> [true true java.lang.Double]

; operations on "double" yield "double" as expected:

(whatf (*(double 1) (double 1)))
;=> [true true java.lang.Double]

; operations on "float" force to "double" immediately:

(whatf (*(float 1) (float 1)))
;=> [true true java.lang.Double]

; of course one can always cast, but what's the use of that:

(whatf (float (*(float 1) (float 1))))
[false true java.lang.Float]

Таким образом, программисту рекомендуется не думать с точки зрения точности и позволить Clojure выбирать за него/нее, а Clojure во всем выбирает двоичный код IEEE64. В этом суть дела?


person David Tonhofer    schedule 09.09.2019    source источник
comment
В Clojure in Action есть таблица числовых типов. Нет упоминания о float, только double (точнее, Java double). Так что. Оставайтесь с двойником!   -  person David Tonhofer    schedule 10.09.2019


Ответы (1)


Я бы сказал, что Clojure/Java упрощает использование только 64-битного типа Java double по нескольким причинам:

  1. double - это тип по умолчанию, который вы получаете, когда пишете число с плавающей запятой, например. 1,0
  2. double — тип по умолчанию, возвращаемый при выполнении арифметических операций, возвращающих тип с плавающей запятой.
  3. Для конструкции цикла и параметра функции, а также возвращаемых значений, для которых вы хотите использовать примитивные значения Java, Clojure поддерживает двойное значение, но не плавающее.

Можно использовать массивы с плавающей запятой и отдельные значения с плавающей запятой, но вам придется немного поработать над этим.

person andy_fingerhut    schedule 09.09.2019
comment
Можно использовать массивы значений с плавающей запятой и отдельные значения с плавающей запятой, но вам придется немного поработать над этим. Что ж, я не думаю, что это того стоит. Решение несколько абстрагироваться от ширины представления с плавающей запятой в первую очередь хорошо с ECMAScript в качестве целевого языка. Интересно, было ли это сделано намеренно? - person David Tonhofer; 10.09.2019
comment
Я только что обнаружил, что есть spec для double, но не для float. Подходит. - person David Tonhofer; 10.09.2019