Clojure округление до десятичных знаков
У меня есть строки, которые представляют десятичные значения,
ex: "0.010", "0.0100000" "00.01000"
Я хочу округлить их до указанного формата,
ex: #. ##
В Java мы имеем:
public BigDecimal setScale(int newScale, RoundingMode roundingMode) {
return setScale(newScale, roundingMode.oldMode);
}
Каков наилучший подход для достижения этого в Clojure вместо использования взаимодействия?
Ответы
Ответ 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))