0
votes

Because of a documented rounding issue in Delphi XE2, we are using a special rounding unit available on the Embarcadero site named DecimalRounding_JH1 to achieve true bankers rounding. A link to the unit can be found here:

DecimalRounding_JH1

Using this unit's DecimalRound function with numbers containing a large number of decimal place we

This is the rounding routine from the DecimalRounding_JH1 unit. In our example we call this DecimalRound function with the following parameters (166426800, 12, MaxRelErrDbl, drHalfEven) where maxRelErrDbl = 2.2204460493e-16 * 1.234375 * 2

Function DecimalRound(Value: extended; NDFD: integer; MaxRelErr: double;
                         Ctrl: tDecimalRoundingCtrl = drHalfEven): extended;
{ The DecimalRounding function is for doing the best possible job of rounding
  floating binary point numbers to the specified (NDFD) number of decimal
  fraction digits.  MaxRelErr is the maximum relative error that will allowed
  when determining when to apply the rounding rule.  }
var i64, j64: Int64; k: integer; m, ScaledVal, ScaledErr: extended;
begin

  If IsNaN(Value) or (Ctrl = drNone)
    then begin Result := Value; EXIT end;

  Assert(MaxRelErr > 0,
      'MaxRelErr param in call to DecimalRound() must be greater than zero.');

{ Compute 10^NDFD and scale the Value and MaxError: }
  m := 1; For k := 1 to abs(NDFD) do m := m*10;
  If NDFD >= 0
    then begin
      ScaledVal := Value * m;
      ScaledErr := abs(MaxRelErr*Value) * m;
      end
    else begin
      ScaledVal := Value / m;
      ScaledErr := abs(MaxRelErr*Value) / m;
      end;

{ Do the diferent basic types separately: }
  Case Ctrl of
    drHalfEven: begin
      **i64 := round((ScaledVal - ScaledErr));**

The last line is where we get a floating point error.

Any thoughts on why this error is occurring?

1

1 Answers

0
votes

If you get an exception, that means you cannot represent your value as an double within specified error range.

In other words, the maxRelErrDbl is too small.

Try with maxRelErrDbl = 0,0000000001 or something to test if I am right.