Java 设置BigDecimal的特定精度
我有一个需要使用大十进制表示lat/lon的。目前我将lat/lon作为双精度,并将其转换为BigDecimal,但我只需要使用大约12位精度。我还没有弄明白如何设置它。有人能帮我做这个吗?你可以用Java 设置BigDecimal的特定精度,java,bigdecimal,floating-point-precision,Java,Bigdecimal,Floating Point Precision,我有一个需要使用大十进制表示lat/lon的。目前我将lat/lon作为双精度,并将其转换为BigDecimal,但我只需要使用大约12位精度。我还没有弄明白如何设置它。有人能帮我做这个吗?你可以用 问题的题目是关于精确性的。区分尺度和精度。刻度是小数位数。您可以将精度视为的数量,也称为有效数字 Clojure中的一些示例 (.比例尺0.00123M);5. (.精度0.00123M);3. (在Clojure中,M指定了一个BigDecimal文本。如果您愿意,可以将Clojure翻译成Ja
问题的题目是关于精确性的。区分尺度和精度。刻度是小数位数。您可以将精度视为的数量,也称为有效数字 Clojure中的一些示例
(.比例尺0.00123M);5.
(.精度0.00123M);3.
(在Clojure中,M
指定了一个BigDecimal文本。如果您愿意,可以将Clojure翻译成Java,但我发现它比Java更紧凑!)
您可以轻松地增加比例:
(.setScale 0.00123M 7);0.0012300M
但不能用完全相同的方法减小比例:
(.setScale 0.00123m3);算术异常舍入是必需的
您还需要通过舍入模式:
(.setScale 0.00123m3大十进制/四舍五入半偶数);
; 注意:BigDecimal希望您使用MathContext舍入
; 常数,但我现在手头没有。
因此,很容易改变比例。但是精确性呢?这并不像你希望的那么容易
很容易降低精度:
(.round 3.14159M(java.math.MathContext.3));3.14米
但如何提高精度并不明显:
(.round 3.14159M(java.math.MathContext.7));3.14159米(意外)
对于持怀疑态度的人来说,这不仅仅是没有显示尾随零的问题:
(.precision(.round 3.14159M(java.math.MathContext.7));6.
; (同上,仍属意外)
FWIW,Clojure小心处理尾随的零,并将显示它们:
4.0000M;4.000米
(.精度4.0000M);5.
回到正轨上。。。您可以尝试使用构造函数,但它不会将精度设置为高于您指定的位数:
(BigDecimal.“3”(java.math.MathContext.5));3米
(BigDecimal.“3.1”(java.math.MathContext.5));3.1米
因此,没有快速改变精度的方法。我在写这个问题和我正在做的一个项目时,花了很多时间来解决这个问题。我认为这充其量是一个疯狂的API,最坏的是一个bug。人。真的吗
因此,据我所知,如果要更改精度,需要执行以下步骤:
(def x 0.000691M);输入号码
(def p'1);期望精度
(def s'(+(.scale x)p'((.precision x)));理想的新规模
(.setScale x s'大十进制/四舍五入半偶数)
; 0.0007M
我知道,这是很多步骤只是为了改变精度
为什么BigDecimal还没有提供呢?我忽略了什么吗
BigDecimal decPrec = (BigDecimal)yo.get("Avg");
decPrec = decPrec.setScale(5, RoundingMode.CEILING);
String value= String.valueOf(decPrec);
通过这种方式,您可以设置BigDecimal
的特定精度
decPrec的值为1.5726903423607562595809913132345426
四舍五入为1.57267
请尝试此代码
Integer perc = 5;
BigDecimal spread = BigDecimal.ZERO;
BigDecimal perc = spread.setScale(perc,BigDecimal.ROUND_HALF_UP);
System.out.println(perc);
结果:0.00000您是否尝试过给构造函数一个MathContext?如果我没看错的话,您说的是小数点,而不是浮点精度。至少接受的答案将产生12位小数,而不是12位精度。Duh。回顾我得到的错误,它说四舍五入是必要的。我只做了。设置刻度(12)。一旦我确认它有效,我会按回答的那样做。谢谢。我不知道为什么它不像铸造那样只使用默认的舍入方法,我只见过舍入一半。这相当迂腐关于
BigDecimal.round(新的MathContext(精度,RoundingModel.round_-HALF_偶数))
呢?@PaŭloEbermann你是在问还是在建议?你试过了吗?介意分享我在回答中所列举的例子的详细结果吗?如果是这样的话,我认为这需要一个单独的答案。对于任何像我这样不懂Clojure的人,我认为这里显示的解决方案是x.setScale(x.scale()+p-x.precision(),RoundingMode.HALF_UP)
,其中x
是要舍入的BigDecimal
,p
是您要保留的有效数字的数量。这对我有用,但如果我错了,请纠正我@Nateowami我喜欢你的解决方案,但不幸的是,它似乎不能在角落的情况下正常工作,例如99.99。您的语句(3个有效数字)将其转换为100.0,而它应该仅为100。有一个额外的有效数字,因为99到99的“溢出”100@Kr1z说得好。猜测这是这个答案的局限性。我能想到的唯一一件事就是事后检查并再次取整数字是否有误。我认为它不可能第二次添加一个数字。
Integer perc = 5;
BigDecimal spread = BigDecimal.ZERO;
BigDecimal perc = spread.setScale(perc,BigDecimal.ROUND_HALF_UP);
System.out.println(perc);