Java四舍五入到小数点后15位

Java Rounding to 15 decimal place

我有以下代码将远期汇率四舍五入到小数点后 15 位。当_ForwardRate为13,555.0时,结果return错误。

public double round(double Number, int Decimal_Place) {     
    if (Number==0) return 0;
    double _plug = 0.000001;
    if (Number < 0) {
        _plug = -0.000001;
    }
    //Sometime a number is rounded down to 2.22499999999 by java. 
    //Actual precision is 2.245.  Without this plug, a 2 dp rounding result
    //in 2.22 when it should be 2.23
    double _newNumber = Number;
    if (Decimal_Place==2) {
        _newNumber = _newNumber+_plug;      
    }

    double _number_abs = Math.abs(_newNumber);  
    double _factor = Math.pow(10, Decimal_Place);
    double _rd = Math.round(_number_abs * _factor);
    double _r = _rd/_factor;
    if (Number <= 0)
        _r = _r * -1;

    return _r;
}

Double _ForwardRate = getForward_rate();
BigDecimal _fwdrate_bd = BigDecimal.valueOf(_ForwardRate.doubleValue());
_ForwardRate = round(new Double(_fwdrate_bd.doubleValue()), 15);

当前结果

9,223.372036854777

预期结果

13,555.000000000000000

考虑:

    double _number_abs = Math.abs(_newNumber);  

此时,_number_abs包含值13555.0

    double _factor = Math.pow(10, Decimal_Place);

现在 _factor 包含 1.0E15

    double _rd = Math.round(_number_abs * _factor);

根据 Javadoc

Math.round() Returns the closest long to the argument, with ties rounding to positive infinity.

由于_number_abs * _factor1.3555E19,大于Long.MAX_VALUE,结果是Long.MAX_VALUE,即"closest"Long给定的值。

你的问题是Math.round(double a)returnslong,你溢出 .

一个简单的方法是使用 BigDecimal:

public static double round(double number, int decimalPlaces) {
    return BigDecimal.valueOf(number)
                     .setScale(decimalPlaces, RoundingMode.HALF_UP)
                     .doubleValue();
}

这允许您控制舍入模式。请注意,Math.round() 进行的舍入是 HALF_CEILINGsetScale() 不支持。

如果您需要那种精确度,您可能需要考虑使用 BigDecimal 进行所有数学运算。