我正在尝试使用this.SomeProperty
格式化资金。我想要cl-format
。我得到格式字符串(f 12345.555) ;=> "12,345.56"
的小数,我得到逗号分隔符"~$"
。我如何组合它们?
答案 0 :(得分:6)
使用Common Lisp,我建议使用支持locales的cl-l10n
并定义~N
。或者,您可以自己动手:
(defun money (stream number colonp atsignp &optional (decimal-places 2))
(multiple-value-bind (integral decimal) (truncate number)
(format stream
(concatenate 'string
"~"
(and colonp ":")
(and atsignp "@")
"D"
"~0,vf")
integral
decimal-places
(abs decimal))))
(setf *read-default-float-format* 'double-float)
(format nil "~2:@/money/" 123456789.123456789)
=> "+123,456,789.12"
现在,对于Clojure,似乎~/
尚不支持cl-format
,因此您无法直接复制上述代码。使用Java库可能更快(参见例如this question或this other one)。
答案 1 :(得分:0)
问题的一部分是~:d
指令仅在传递整数时添加逗号(无论它是浮点数还是整数),即如果除了零以外的任何其他值小数点,~:d
只是打印出数字。这对于CL format
以及Clojure的cl-format
来说都是如此。
解决方案是将数字拆分为整数和小数,然后单独格式化。一种方法是使用truncate
函数,它既不是Clojure也不是它的标准库提供的。这是一种方法,使用floor
中的ceil
和clojure.math.numeric-tower
。 (感谢coredump指出我早期版本中的错误。)
(defn truncate [x]
(if (neg? x)
(ceil x)
(floor x)))
(defn make-money [x]
(let [int-part (truncate x)
dec-part (- x int-part)]
(cl-format nil "~:d~$" int-part dec-part)))
(make-money 123456789.123456789) ;=> "123,456,7890.12"
请注意,这仅适用于正数。 (编辑:正如哈维在评论中指出的那样,这不是一个解决方案,因为在最后一次评论之后有一个4位数组。)
这回答了OP的问题(编辑:不是真的 - 见上文),但我注意到在Common Lisp中,~$
的行为略有不同;默认情况下,它在小数点之前打印出一个初始零(至少在我尝试的实现中 - 不确定这是否标准化)。这可以通过自定义~f
指令来避免 - 这在Clojure中也是如此(详见Peter Seibel's introduction):
(defun make-money (x)
(let* ((int-part (truncate x))
(dec-part (- x int-part)))
(format nil "~:d~0,2f" int-part dec-part)))
如果数字太大,您可以使用此定义获得意外结果。我确信有办法通过调整定义来避免这个问题,而且无论如何,正如Joshua Taylor的评论所指出的那样,在Common Lisp中还有其他更好的方法可以做到这一点。