为什么BigDecimal没有像我预期的那样工作?

时间:2016-12-12 17:39:02

标签: java

这是评论中的代码和结果:

我原以为numB2应该是16.7500,numB3 = 16.7500,numB4 = 16.7和numB5 = 16.75。但它们并不像我预期的那样。为什么呢?

public void testBigDecimal()
{
    float num = 16.7499924f;

    int digitCount = 4;
    MathContext mContext = new MathContext(digitCount, RoundingMode.UP);
    BigDecimal numB = new BigDecimal(num, mContext);
    System.out.println("16.7499924f with MathContext(precision) of 4 =" + numB.floatValue());// 16.75
    numB.setScale(4, RoundingMode.UP);
    System.out
            .println("16.7499924f with MathContext(precision) of 4 and after setScale of 4 =" + numB.floatValue());// 16.75

    BigDecimal numB2 = new BigDecimal(num);
    System.out.println("16.7499924f without MathContext(precision =" + numB2.floatValue());// 16.749992
    numB2.setScale(4, RoundingMode.UP);
    System.out.println("16.7499924f without MathContext(precision) and after setScale of 4 =" + numB2.floatValue());// 16.749992

    BigDecimal numB3 = new BigDecimal(num);
    numB3.setScale(4, RoundingMode.UP);
    System.out.println("16.7499924f without MathContext(precision) but with setScale of 4 =" + numB3.floatValue());// 16.749992

    BigDecimal numB4 = new BigDecimal(num);
    numB4.setScale(1, RoundingMode.UP);
    System.out.println("16.7499924f without MathContext(precision) but with setScale of 1 =" + numB4.floatValue());// 16.749992

    BigDecimal numB5 = new BigDecimal(num);
    numB5.setScale(2, RoundingMode.UP);
    System.out.println("16.7499924f without MathContext(precision) but with setScale of 2 =" + numB5.floatValue());// 16.749992

}

2 个答案:

答案 0 :(得分:5)

BigDecimal是不可变的。你忽略了setScale()的结果。所以你所拥有的基本上都是noops。

另外,使用字符串创建BigDecimal。并且不要将其打印为浮点值。在这样做时你会失去精确度,这是首先使用BigDecimal的重点:

String num = "16.7499924";

int digitCount = 4;
MathContext mContext = new MathContext(digitCount, RoundingMode.UP);
BigDecimal numB = new BigDecimal(num, mContext);
System.out.println("16.7499924f with MathContext(precision) of 4 =" + numB.toPlainString());
numB = numB.setScale(4, RoundingMode.UP);
System.out.println("16.7499924f with MathContext(precision) of 4 and after setScale of 4 =" + numB.toPlainString());

答案 1 :(得分:1)

由于VertexInterp是不可变的,BigDecimal会返回一个应用了缩放操作的新setScale(4, RoundingMode.UP);,但它不会影响原始变量。因此,BigDecimal代替numB.setScale(4, RoundingMode.UP);来代替numB2 = numB2.setScale(4, RoundingMode.UP);,因为它无用,因为它会在下一步中覆盖它。

此外,您使用的是BigDecimal numB2 = new BigDecimal(num);,但之后又将其转换为BigDecimal。这可能是不精确的,正如文档陈述float

  

请注意,即使返回值是有限的,此转换也可能会丢失有关BigDecimal值精度的信息。