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

时间:2015-07-08 15:52:41

标签: java soap double precision bigdecimal

I NEED to be sending a value as 'double', however I am:

  1. Taking a value as a long
  2. Converting it to BigDecimal
  3. Calling method scaleByPowerOfTen on the BigDecimal (using '-2' to make cents a whole amount value).
  4. Calling doubleValue() on the BigDecimal to get the needed value as double.

Now I know that double values lose precision when you apply arithmetic operations on them, however what could I possibly get if I try to send a double value as-is based on BigDecimal, such as (I believe) the above scenario is.

This is important as I have to be sending money values over SOAP in this manner - no other way.

I also have the scenario where the BigDecimal is created using as a String, then doubleValue() is called on it. What could I get in this case ?

EDIT: Sample code for this:

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

As for the case where the amount is provided as String:

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

UPDATE

Now that I have sample code, I just thought I can test and see, so I did a for loop and used System.out.println: so far so good, the values are correct, so I believe this will be the same when sent through SOAP. Please correct me if I'm wrong.

3 个答案:

答案 0 :(得分:1)

Since one cent is equal to 1/100 of a dollar, and since the number 1/100 or 0.01 cannot be represented exactly as a binary floating-point number, some slight loss of accuracy will occur. In your particular example of $18.52, the resulting double will hold the closest double value to 18.52, but it will not be exactly equal to 18.52.

答案 1 :(得分:0)

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

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

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

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

答案 2 :(得分:0)

BigDecimal的{​​{3}}似乎达到了double的自然准确性。

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

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

amountInWholeUnits.doubleValue();

检查比例,如果不是0(如本例所示),则确实:

Double.parseDouble(this.toString());

因此,您计划的操作的结果基本上是double,与18.52尽可能接近double

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