BigDecimal setScale 方法的工作方式与我期望的完全相反

Seb*_*oek 5 java rounding bigdecimal

考虑这个代码:

import java.math.BigDecimal;
import java.math.RoundingMode;

public class RoundingTests {

    public static void main(String[] args) {
        BigDecimal bd1 = new BigDecimal(265.345d);
        BigDecimal bd2 = new BigDecimal(265.335d);

        System.out.println("Setting scale 265.345: " + bd1.setScale(2, RoundingMode.HALF_EVEN));
        System.out.println("Setting scale 265.335: " + bd2.setScale(2, RoundingMode.HALF_EVEN));
    }
}
Run Code Online (Sandbox Code Playgroud)

输出是:

Setting scale 265.345: 265.35
Setting scale 265.335: 265.33
Run Code Online (Sandbox Code Playgroud)

现在这与我的预期完全相反。随着RoundingMode.HALF_EVEN(也称为银行家四舍五入)我期待这两个值成为价值265.34

请注意,我不是BigDecimal.round故意使用该方法,因为它也不是我需要的。如果我添加此代码(并导入 java.math.MathContext):

System.out.println("Rounding 265.345: " + bd1.round(new MathContext(2, RoundingMode.HALF_EVEN)));
System.out.println("Rounding 265.335: " + bd2.round(new MathContext(2, RoundingMode.HALF_EVEN)));
Run Code Online (Sandbox Code Playgroud)

然后输出是:

Rounding 265.345: 2.7E+2
Rounding 265.335: 2.7E+2
Run Code Online (Sandbox Code Playgroud)

这是意料之中的,也在BigDecimal setScale 和 round 中进行了解释,但这意味着它对我的目的来说基本上没用。

有人可以在这里解释 setScale 的问题吗?

更新:所以这只是另一个浮点问题,没有简单的方法来修复它,而不是从一开始就使用 BigDecimals。

Jon*_*eau 1

您可能想要更改代码以BigDecimal.valueOf()使用new BigDecimal().

代码

  Double dValue = 265.345d;
  Double dValue2 = 265.335d;
  BigDecimal value = BigDecimal.valueOf(dValue);
  BigDecimal bd1 = new BigDecimal(265.345d);
  BigDecimal bd2 = new BigDecimal(265.335d);
  BigDecimal value2 = BigDecimal.valueOf(dValue2);
  System.out.println("BigDecimal.valueOf(dValue);");
  System.out.println(value.toPlainString());
  System.out.println(String.valueOf(dValue));
  value = value.setScale(2, BigDecimal.ROUND_HALF_EVEN);
  System.out.println(value);
  System.out.println("BigDecimal.valueOf(dValue2);");
  System.out.println(value2.toPlainString());
  System.out.println(String.valueOf(dValue2));
  value2 = value2.setScale(2, BigDecimal.ROUND_HALF_EVEN);
  System.out.println(value2);
  System.out.println("BigDecimal bd1 = new BigDecimal(265.345d);");
  System.out.println(bd1.setScale(2, BigDecimal.ROUND_HALF_EVEN));
  System.out.println("BigDecimal bd2 = new BigDecimal(265.335d);");
  System.out.println(bd2.setScale(2, BigDecimal.ROUND_HALF_EVEN));
Run Code Online (Sandbox Code Playgroud)

输出:

BigDecimal.valueOf(dValue);
265.345
265.345
265.34
BigDecimal.valueOf(dValue2);
265.335
265.335
265.34
BigDecimal bd1 = new BigDecimal(265.345d);
265.35
BigDecimal value2 = BigDecimal.valueOf(dValue2);
265.33
Run Code Online (Sandbox Code Playgroud)