Java 8 BigDecimal Multiply方法在倒置时失去精度



java 8在这里。根据Google的说法:

  • 将磅转换为千克:乘以0.453592
  • 将千克转换为磅:乘以2.20462
  • 将英寸转换为米:乘以0.0254
  • 将仪表转换为英寸:乘以39.3701

所以我提出了这个小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.

我所关心的是,帝国< ->公制转换是准确的2个小数点,最终输出始终是准确的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.45。和2.2*0.45=0.99解释结果。

您已经根据乘法的结果设置了比例,而不是在乘数上设置比例。基本上,最后一个支架在错误的位置。应该是:

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

这是校正的代码。

对乘法的比例和半_up参数?您仅将其添加到BigDecimal中。

我认为您想要:

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

chaning量表至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个小数位:

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

因此," 0,0254" 被四舍五入到 0.03 ,它不符合您的"反向"转换因子的 39.37 。这就是为什么您的逆转不等于原始值的原因。

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

如果要显示为:

的值
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.

最新更新