Подтвердить что ты не робот

Clojure округление до десятичных знаков

У меня есть строки, которые представляют десятичные значения, ex: "0.010", "0.0100000" "00.01000"

Я хочу округлить их до указанного формата, ex: #. ##

В Java мы имеем:

public BigDecimal setScale(int newScale, RoundingMode roundingMode) {
    return setScale(newScale, roundingMode.oldMode);
}

Каков наилучший подход для достижения этого в Clojure вместо использования взаимодействия?

4b9b3361

Ответ 1

Вы можете использовать Clojure format для этой цели. Он должен предоставить вам решение вашей проблемы. Вот несколько примеров и ссылок:

user=> (format "%.2f" 0.010)
"0.01"
user=> (format "%.2f" 0.010000)
"0.01"
user=> (format "%.2f" 00.010000000)


user=> (doc format)
-------------------------
clojure.core/format
([fmt & args])
  Formats a string using java.lang.String.format, see java.util.Formatter for format
  string syntax

Ответ 2

Это слегка измененная версия примера в clojure-doc.org:

(defn round2
  "Round a double to the given precision (number of significant digits)"
  [precision d]
  (let [factor (Math/pow 10 precision)]
    (/ (Math/round (* d factor)) factor)))

@number23_cn ответ правильный для многих случаев. Однако реальная функция округления с аргументом точности может быть полезна, если, например, вы хотите отобразить последовательность с округленным числом. Затем вы можете просто сопоставить round2 над последовательностью, чтобы отформатировать каждый номер сразу:

(map (partial round2 2) [0.001 10.123456 9.5556])

который возвращает

(0.0 10.12 9.56)

Это более полезно для более длительной последовательности, конечно.


Другой вариант - использовать cl-format, который представляет собой реализацию Clojure Common Lisp format. Он похож на Clojure format (который основан на java.util.Formatter), но имеет другой синтаксис и допускает некоторые причудливые трюки.

(clojure.pprint/cl-format nil "~,2f" 23.456)
; => "23.46"

Директива ~{ ~} позволяет обрабатывать последовательности, как в первом примере выше:

(clojure.pprint/cl-format nil "~{ ~,2f~}" [0.001 10.123456 9.5556])
; => " 0.00 10.12 9.56"

~{ ~} ожидает увидеть последовательность в качестве аргумента и будет есть элементы последовательности один за другим, используя любые директивы между ~{ и ~}.

(глава о format от Peter Seibel Практическая общая Lisp является лучшим введением в Common Lisp format и, следовательно, к Clojure cl-format, imo. Документация на CL format в обычном источнике, Common Lisp Hyperspec, иногда бывает сложно использовать. на CL format в Общий Lisp Язык немного лучше.)

Ответ 3

Принятый ответ рекомендует format, но format не округляет (как указано в одном из комментариев). Другой ответ (по Марсу) не будет работать для BigDecimal s. Чтобы округлить bigdec до нескольких десятичных знаков в Clojure, единственным решением, которое я нашел, является использование Java interop:

(defn round [s]
  (fn [n]
    (assert (bigdec? n))
    (.setScale n s RoundingMode/HALF_EVEN)))

(def round4 (round 4))