设置 BigDecimal 的特定精度

新手上路,请多包涵

我有一个 XSD ,要求我对纬度/经度使用 BigDecimal。我目前将纬度/经度作为双精度数,并将它们转换为 BigDecimal,但我只需要使用大约 12 位精度。我一直无法弄清楚如何设置它。谁能帮我这个?

原文由 Jason 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 746
2 个回答

题目问的是精度。 BigDecimal 区分小数位数和精度。比例是小数位数。您可以将精度视为 有效数字 的个数,也称为有效数字。

Clojure 中的一些示例。

 (.scale     0.00123M) ; 5
(.precision 0.00123M) ; 3

(在 Clojure 中, M 指定一个 BigDecimal 文字。您可以根据需要将 Clojure 翻译成 Java,但我发现它比 Java 更紧凑!)

您可以轻松地增加规模:

 (.setScale 0.00123M 7) ; 0.0012300M

但是您不能以完全相同的方式 减小 比例:

 (.setScale 0.00123M 3) ; ArithmeticException Rounding necessary

您还需要通过舍入模式:

 (.setScale 0.00123M 3 BigDecimal/ROUND_HALF_EVEN) ;
; Note: BigDecimal would prefer that you use the MathContext rounding
; constants, but I don't have them at my fingertips right now.

因此,更改比例很容易。但是精度呢?这并不像您希望的那么容易!

很容易 降低 精度:

 (.round 3.14159M (java.math.MathContext. 3)) ; 3.14M

但是如何 提高 精度并不明显:

 (.round 3.14159M (java.math.MathContext. 7)) ; 3.14159M (unexpected)

对于持怀疑态度的人,这 不仅仅是 不显示尾随零的问题:

 (.precision (.round 3.14159M (java.math.MathContext. 7))) ; 6
; (same as above, still unexpected)

FWIW,Clojure 对尾随零非常小心, 并将 显示它们:

 4.0000M ; 4.0000M
(.precision 4.0000M) ; 5

回到正轨…您可以尝试使用 BigDecimal 构造函数,但它不会将精度设置为高于您指定的位数:

 (BigDecimal. "3" (java.math.MathContext. 5)) ; 3M
(BigDecimal. "3.1" (java.math.MathContext. 5)) ; 3.1M

所以,没有快速的方法来改变精度。在写这个问题和我正在从事的项目时,我花了很多时间来解决这个问题。我认为这充其量是一个 CRAZYTOWN API,最坏的情况是一个错误。人们。严重地?

所以,据我所知,如果你想改变精度,你需要执行以下步骤:

  1. 查找当前精度。
  2. 查找当前比例。
  3. 计算尺度变化。
  4. 设置新比例

这些步骤,作为 Clojure 代码:

 (def x 0.000691M) ; the input number
(def p' 1) ; desired precision
(def s' (+ (.scale x) p' (- (.precision x)))) ; desired new scale
(.setScale x s' BigDecimal/ROUND_HALF_EVEN)
; 0.0007M

我知道,这只是为了改变精度而采取的很多步骤!

为什么 BigDecimal 不提供这个?我忽略了什么吗?

原文由 David J. 发布,翻译遵循 CC BY-SA 3.0 许可协议

您可以使用 setScale() 例如

double d = ...
BigDecimal db = new BigDecimal(d).setScale(12, BigDecimal.ROUND_HALF_UP);

原文由 Peter Lawrey 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题