Java 8 BigDecimal乘法方法在被反转时失去精度

时间:2018-02-19 20:46:05

标签: java precision bigdecimal

Java 8在这里。根据谷歌的说法:

所以我掀起了这个小Java代码:

public class MeasurementConverter {
    private static final int SCALE = 2;

    public static void main(String[] args) {
        new MeasurementConverter().run();
    }

    private void run() {
        BigDecimal hundredLbs = new BigDecimal(100.00);
        BigDecimal hundredInches = new BigDecimal(100.00);

        System.out.println(hundredLbs + " pounds is " + poundsToKilos(hundredLbs) + " kilos and converts back to " + kilosToPounds(poundsToKilos(hundredLbs)) + " pounds.");
        System.out.println(hundredInches + " inches is " + inchesToMeters(hundredInches) + " meters and converts back to " + metersToInches(inchesToMeters(hundredInches)) + " inches.");
    }

    private BigDecimal metersToInches(BigDecimal meters) {
        return meters.multiply(new BigDecimal("39.3701").setScale(SCALE, BigDecimal.ROUND_HALF_UP));
    }

    private BigDecimal inchesToMeters(BigDecimal inches) {
        return inches.multiply(new BigDecimal("0.0254").setScale(SCALE, BigDecimal.ROUND_HALF_UP));
    }

    private BigDecimal kilosToPounds(BigDecimal kilos) {
        return kilos.multiply(new BigDecimal("2.20462").setScale(SCALE, BigDecimal.ROUND_HALF_UP));
    }

    private BigDecimal poundsToKilos(BigDecimal pounds) {
        return pounds.multiply(new BigDecimal("0.45359").setScale(SCALE, BigDecimal.ROUND_HALF_UP));
    }
}

运行时打印出来:

100 pounds is 45.00 kilos and converts back to 99.0000 pounds.
100 inches is 3.00 meters and converts back to 118.1100 inches.

虽然我期待打印出来:

100.00 pounds is 45.00 kilos and converts back to 100.00 pounds.
100.00 inches is 3.00 meters and converts back to 100.00 inches.

我所关心的是,Imperial< - > Metric转换精确到2位小数,并且最终输出始终精确到2位小数。 任何人都可以看到我出错的地方以及解决方法是什么?

4 个答案:

答案 0 :(得分:2)

你的括号搞砸了。考虑一下:

kilos.multiply(new BigDecimal("2.20462").setScale(SCALE, BigDecimal.ROUND_HALF_UP));

首先,您在2.20462上设置比例,结果为2.20,然后相乘。

现在考虑反向转换:

pounds.multiply(new BigDecimal("0.45359").setScale(SCALE, BigDecimal.ROUND_HALF_UP));

在这里,您有效地乘以0.452.2*0.45=0.99解释了结果。

您已在乘法结果上设置了比例,而不是在乘数上。基本上最后一个括号是在错误的地方。它应该是这样的:

pounds.multiply(new BigDecimal("0.45359")).setScale(SCALE, BigDecimal.ROUND_HALF_UP);

这是corrected code

答案 1 :(得分:1)

不是SCALE和HALF_UP参数的乘法?你只将它添加到BigDecimal。

我想你想要:

inches.multiply(new BigDecimal("0.0254"), new MathContext(SCALE, RoundingMode.HALF_UP));

将SCALE转换为8并将代码与MathContext一起使用导致:

100 pounds is 45.35900 kilos and converts back to 99.999359 pounds.
100 inches is 2.5400 meters and converts back to 100.00005 inches.

答案 2 :(得分:0)

您的转化因素已关闭。您将转换因子四舍五入到小数点后两位:

private static final int SCALE = 2;
[...]    
new BigDecimal("0.0254").setScale(SCALE, BigDecimal.ROUND_HALF_UP)

因此," 0,0254" 被四舍五入到 0.03 ,这不适合你的"反向&#34 ;转换因子 39.37 。这就是为什么你的逆转不等于原始价值的原因。

答案 3 :(得分:0)

您正在转换过程中进行四舍五入。因此,反向操作的输入值已经关闭。

如果要将值显示为:

100.00 pounds is 45.00 kilos and converts back to 100.00 pounds.
100.00 inches is 3.00 meters and converts back to 100.00 inches.

从您的所有私有方法中删除setScale。例如:

private BigDecimal metersToInches(BigDecimal meters) {
    return meters.multiply(new BigDecimal("39.3701"));
}

然后您可以使用所需格式简单地格式化输出:

private BigDecimal formatOutput(BigDecimal value) {
    return value.setScale(0, BigDecimal.ROUND_HALF_UP).setScale(SCALE);
}

最后:

System.out.println(hundredLbs + " pounds is " + formatOutput(poundsToKilos(hundredLbs)) + " kilos and converts back to " + formatOutput(kilosToPounds(poundsToKilos(hundredLbs))) + " pounds.");
System.out.println(hundredInches + " inches is " + formatOutput(inchesToMeters(hundredInches)) + " meters and converts back to " + formatOutput(metersToInches(inchesToMeters(hundredInches))) + " inches.");

给出:

100.00 pounds is 45.00 kilos and converts back to 100.00 pounds.
100.00 inches is 3.00 meters and converts back to 100.00 inches.

或者,如果要显示带小数位的值,只需将formatOutput方法更改为:

private BigDecimal formatOutput(BigDecimal value) {
    return value.setScale(SCALE, BigDecimal.ROUND_HALF_UP);
}

将以下列方式打印出值(我会说它更好更正确!)

100.00 pounds is 45.36 kilos and converts back to 100.00 pounds.
100.00 inches is 2.54 meters and converts back to 100.00 inches.