【问题标题】:Format a 'numeric' string as a number将“数字”字符串格式化为数字
【发布时间】:2018-09-02 03:22:06
【问题描述】:

我想在 Clojure 中将“数字”字符串格式化为“字符串数字”。这是格式掩码:

"#,###,###,##0.00"

给定字符串“9999.99”,我希望收到“9,999.99”。

我如何在 Clojure 中做到这一点而不求助于编写转换器函数,即使用 format 或类似的东西?

【问题讨论】:

    标签: clojure


    【解决方案1】:

    在您的问题域中,二进制浮点(例如 IEEE-754)的缺点和限制似乎给您带来了一些困难。也许您应该考虑利用 Clojure 中已经内置的 BigDecimal 支持。在 Clojure 中,BigDecimal 常量和浮点常量之间的区别是单个字符;例如1.2 是 Double,而 1.2M 是 BigDecimal。 bigdec 函数可用于即时将事物转换为 BigDecimal。例如,

    (format "%,.2f" (bigdec "9999999999999999.12"))
    

    生产

    "9,999,999,999,999,999.12"
    

    正如预期的那样。 *+-/ 等算术函数也可以正常工作。

    但是,这并不能解决您的基本问题。如果您的格式字符串不遵循 Java/Clojure 格式字符串约定,您将不得不编写一个转换器函数。

    祝你好运。

    【讨论】:

    • 我知道format是一个继承函数。但是如果它只接受一个字符串作为输入会好很多。我在服务器上使用org.joda.money,并希望在浏览器中进行一些格式化。
    • 格式字符串遵循的约定对问题并不重要,只是更容易/更短地使用它,而不是用文字描述所需的输出。
    • 那你是在浏览器中使用 ClojureScript 吗?
    • 是的,我是浏览器中的 ClojureScript/Fulcro 和后端的 Clojure/Fulcro(包括 Ring)。
    • 你为什么要问?我现在实际上不是从 string->string 进行翻译,而是从 org.joda.money ->string 中的底层 BigDecimal 进行翻译。
    【解决方案2】:

    您可以在格式说明符中使用,

    (format "%,.2f" (float (clojure.edn/read-string "9999")))
    => "9,999.00"
    (format "%,.2f" (Double/parseDouble "9999.126"))
    => "9,999.13"
    

    更新以包含 bigdec 示例:

    (format "%,.2f" (bigdec "9999999999999999.12"))
    => "9,999,999,999,999,999.12"
    

    【讨论】:

    • (format "%,.2f" (Double/parseDouble "9999999999999999.12")) 给出 "10,000,000,000,000,000.00" 和 (format "%,.2f" (float (clojure.edn/read-string "999999999999999. "))) 在 "10,000,000,272,564,224.00" 处更糟。中间使用 float/double 会降低精度。
    【解决方案3】:

    您可以使用NumberFormat 执行此操作。我也喜欢另一个答案(详见the Java 10 Formatter docs):

    (ns tst.demo.core
      (:use demo.core tupelo.core tupelo.test)
      (:import [java.text NumberFormat]
               [java.util Locale]))
    
    (dotest
      (let [value (Double/valueOf "1234567.89")
            nf    (NumberFormat/getNumberInstance (Locale/US))
            s1a   (.format nf (.doubleValue value))
            s1b   (format "%,05.2f" value)]
        (spyx s1a)
        (spyx s1b))
    
    s1a => "1,234,567.89"
    s1b => "1,234,567.89"
    
      (let [value (Double/valueOf "1.2")
            nf    (NumberFormat/getNumberInstance (Locale/US))
            s1a   (.format nf (.doubleValue value))
            s1b   (format "%,05.2f" value)]
        (spyx s1a)
        (spyx s1b)))
    
    s1a => "1.2"
    s1b => "01.20"
    

    更新

    这是 BigDecimal 的操作方法,首先使用 Java 互操作,然后使用内置 Clojure 函数bigdec

    (format "%,05.2f" (BigDecimal. "9999999999999999.12")) => "9,999,999,999,999,999.12"
    (format "%,05.2f" (bigdec      "9999999999999999.12")) => "9,999,999,999,999,999.12"
    

    【讨论】:

    • 有一个名为 bigdec 的 Clojure 函数,您可以使用它来代替互操作。
    猜你喜欢
    • 2010-10-16
    • 1970-01-01
    • 2021-07-09
    • 1970-01-01
    • 1970-01-01
    • 2014-03-15
    • 2021-05-05
    • 1970-01-01
    相关资源
    最近更新 更多