Clojure四舍五入到小数位

问题描述 投票:19回答:4

我有代表十进制值的字符串,例如:“0.010”,“0.0100000”“00.01000”

我想将它们舍入到指定的格式,例如:#。##

在Java中我们有:

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

在Clojure中实现这一目标的最佳方法是什么,而不是使用互操作?

clojure decimal
4个回答
30
投票

你可以使用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

20
投票

这是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,它是Common Lisp的format的Clojure实现。它类似于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"

~{ ~}希望看到一个序列作为参数,并将使用~{~}之间出现的任何指令逐个吃掉序列的元素。

(来自Peter Seibel的chapter on formatPractical Common Lisp是对Common Lisp的format的最好的介绍,因此对Clojure的cl-format,imo。通常来源的documentation on CL's formatCommon Lisp Hyperspec,有时很难使用.section on CL's format中的Common Lisp The Language稍好一些。)


1
投票

接受的答案推荐format,但format没有回合(正如其中一条评论所指出的那样)。另一个答案(火星)不适用于BigDecimals。要将bigdecs舍入到Clojure中的多个小数位,我找到的唯一解决方案是使用Java互操作:

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

(def round4 (round 4)) 

1
投票

在十进制数字上使用Double/ParseDouble后使用函数format将返回一个小数四舍五入到使用format描述的所需小数位数。像这样:

user=> (Double/parseDouble (format "%.2f" 0.009) ) 
0.01

如果进一步计算需要舍入数字,则解析Double非常重要。但是,如果只需要输出舍入数字,则使用format是合适的。

© www.soinside.com 2019 - 2024. All rights reserved.