-4

I have the below codes round the forward rate to 15 decimal place. When _ForwardRate is 13,555.0, the result return is wrong.

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);

Current result

9,223.372036854777

Expected result

13,555.000000000000000
bittersour
  • 937
  • 2
  • 11
  • 32

2 Answers2

1

Your problem is that Math.round(double a) returns long, and you're overflowing.

One easy way to do this, is to use BigDecimal:

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

This allows you to control the rounding mode. Note that the rounding done by Math.round() is a HALF_CEILING which isn't supported by setScale().

You might want to consider doing all you math using BigDecimal, if you need that level of precision.

Andreas
  • 154,647
  • 11
  • 152
  • 247
0

Consider:

    double _number_abs = Math.abs(_newNumber);  

At this point, _number_abs contains the value 13555.0

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

Now _factor contains 1.0E15

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

According to the Javadoc

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

Since _number_abs * _factor is 1.3555E19, which is larger than Long.MAX_VALUE, the result is Long.MAX_VALUE, i.e. the "closest" Long to the given value.

Jim Garrison
  • 85,615
  • 20
  • 155
  • 190