如何在java中将美元金额转换为美分?

时间:2017-05-17 20:01:37

标签: java currency bigdecimal

我有以下程序(取自SO链接What is the best way to convert Dollars (Big Decimal) in Cents (Integer) in java?),将美元兑换成美分。但是,输出并不符合我的预期。

当前输出:

12345
8

预期输出:

12345
9

Main.java

public class Main {

    private static final BigDecimal x100 = new BigDecimal(100);
    static List<BigDecimal> nums = new ArrayList<>();
    static BigDecimal a = new BigDecimal(123.45);
    static BigDecimal b = new BigDecimal(0.09);

    public static void main(String[] args) {
        nums.add(a);
        nums.add(b);
        for (BigDecimal usd : nums) {
            BigDecimal rounded = usd.setScale(2, BigDecimal.ROUND_DOWN);
            BigDecimal bigDecimalInCents = rounded.multiply(x100);
            int cents = bigDecimalInCents.intValueExact();
            System.out.println(cents);
        }
    }

}

2 个答案:

答案 0 :(得分:4)

您的问题是双打不能代表所有值。例如,9/100只能近似。试试System.out.println(new BigDecimal(0.09))。你应该得到0.0899999999999999966693309261245303787291049957275390625。因此,您将其舍入为0.08,然后乘以100.

尝试new BigDecimal(String.valueOf(0.09))

修改 更好的解决方案是使用BigDecimal.valueOf(0.09),这是等效的。

来自BigDecimal(double)的javadoc:

  

将double转换为BigDecimal,它是double的二进制浮点值的精确十进制表示。
  ...
  当double必须用作BigDecimal的源时,请注意此构造函数提供了精确的转换;它不会产生与使用Double.toString(double)方法将double转换为String然后使用BigDecimal(String)构造函数相同的结果。要获得该结果,请使用静态valueOf(double)方法。

对于BigDecimal.valueOf(double)

  

使用Double.toString(double)方法提供的双重规范字符串表示法将double转换为BigDecimal。

     

注意:这通常是将double(或float)转换为BigDecimal的首选方法,因为返回的值等于使用Double的结果构造BigDecimal所产生的值。的toString(双)。

答案 1 :(得分:4)

TL;博士

使用字符串,而非数字文字。

new BigDecimal( "123.45" )

避免浮点

在构建double时,您在代码中隐式引入了BigDecimal类型基元。

new BigDecimal( 123.45 )  // <-- Passing `double` primitive
new BigDecimal( 0.09 )

虽然您认为自己正在传递123.45,但实际上您传递的内容更像123.4500000000000028421709430404007434844970703125。而不是0.09你传递的更像0.0899999999999999966693309261245303787291049957275390625

你打败了使用BigDecimal和货币的目的,这是为了避免inherent inaccuracy of floating-point类型来确定它们的小数。

Java类型floatFloatdoubleDouble全部使用floating point technology。浮点技术在计算中牺牲了执行速度的准确性。适合某些游戏,图形和科学/工程用途,但对金钱不利。

BigDecimal 使用浮点技术。因此计算的执行要慢得多,但结果是准确的。

解决方案:构建BigDecimal时避免使用浮点数。使用字符串。

new BigDecimal( "123.45" )
new BigDecimal( "0.09" )