繁体   English   中英

如果没有对金额执行任何操作,BigDecimal.doubleValue()的准确度

[英]How accurate is BigDecimal.doubleValue() if no operation is applied on the amount

我需要发送一个' 双倍 '的值,但我是:

  1. 价值作为一个长期
  2. 转换BigDecimal
  3. BigDecimal上调用方法scaleByPowerOfTen (使用'-2'使美分成为一个整数值)。
  4. BigDecimal上调用doubleValue()以获得所需的值为double

现在我知道当你对它们应用算术运算时, double值会失去精度, 但是如果我尝试基于BigDecimal发送double值, 我可能会得到什么 ,例如(我相信)上面的场景是。

这很重要,因为我必须以这种方式通过SOAP发送货币价值 - 别无他法。

我还有使用String作为BigDecimal创建的场景,然后在其上调用doubleValue() 在这种情况下我能得到什么?

编辑:示例代码:

long amountInCents = 1852;
BigDecimal amountInWholeUnits = BigDecimal.valueOf(amountInCents).scaleByPowerOfTen(-2);
double amountToSend = amountInWholeUnits.doubleValue();

至于金额是以字符串形式提供的情况:

double amountToSend = new BigDecimal("18.52").doubleValue();

UPDATE

现在我有示例代码,我只是认为我可以测试并看到,所以我做了一个for循环并使用了System.out.println :到目前为止很好,值是正确的,所以我相信这将是相同的发送通过SOAP。 如果我错了,请纠正我。

由于1美分等于1/100美元,并且由于数字1/100或0.01 不能完全表示为二进制浮点数,因此会出现一些轻微的精度损失。 在$ 18.52的特定示例中,结果double将最接近的double值保持为18.52,但它不会完全等于18.52。

Java双打本质上是近似值。 换句话说, 不能保证存在与任何给定浮点值完全对应的double值

BigDecimal通过精确表示浮点值来工作。 但这意味着对于BigDecimal的任何有效值,不能保证存在表示它的double值。 无论你如何创建BigDecimal,都是如此。

如果您需要金额的精确表示,则不能使用双精度表示。 您需要在所有计算过程中继续使用BigDecimal,或者找到符合您需求的整数表示。 经常使用整数的分数,但请记住,计算有时可能涉及分数的一小部分,如果计算多次完成,舍入策略可能会产生很大的影响。

如果你没有计算要做,那么使用一个整数(例如整数仙数)来表示该值就没问题了。

BigDecimalOpenJDK实现似乎达到了double的自然准确性。

BigDecimal.valueOf(1852).scaleByPowerOfTen(-2);

创建一个BigDecimal,其值为(有效) 1852scale-2

amountInWholeUnits.doubleValue();

检查比例,如果它不是0(就像在这种情况下),它会:

Double.parseDouble(this.toString());

所以基本上你计划的操作的结果将是double ,接近18.52double

显然,这也假设所有JDK都做类似的事情(可能不是这种情况)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM