Here you'll find several functions for rounding numbers in different ways

Rounding numbers in different ways

Copyright © 2000 Ernesto De Spirito

Help & Manual authoring tool

Integer rounding

The Round function that comes with Delphi performs what is called "banker's rounding", meaning that a number with a fractional part of 0.5 is rounded sometimes up and sometimes down, always towards the nearest even number. This means that for example Round(3.5) gives 4 while Round(2.5) gives 2.

Here goes a set of functions for rounding numbers, including RoundN which rounds a number "normally" (i.e. RoundN(3.5) is 4 and RoundN(2.5) is 3).

function Sgn(X: Extended): Integer;
// Returns -1, 0 or 1 according to the
// sign of the argument
begin
  if X < 0 then
    Result := -1
  else if X = 0 then
    Result := 0
  else
    Result := 1;
end;


function RoundUp(X: Extended): Extended;
// Returns the first integer greater than or
// equal to a given number in absolute value
// (sign is preserved).
//   RoundUp(3.3) = 4    RoundUp(-3.3) = -4
begin
  Result := Int(X) + Sgn(Frac(X));
end;


function RoundDn(X: Extended): Extended;
// Returns the first integer less than or
// equal to a given number in absolute
// value (sign is preserved).
//   RoundDn(3.7) = 3    RoundDn(-3.7) = -3
begin
  Result := Int(X);
end;


function RoundN(X: Extended): Extended;
// Rounds a number "normally": if the fractional
// part is >= 0.5 the number is rounded up (see RoundUp)
// Otherwise, if the fractional part is < 0.5, the
// number is rounded down (see RoundDn).
//   RoundN(3.5) = 4     RoundN(-3.5) = -4
//   RoundN(3.1) = 3     RoundN(-3.1) = -3
begin
(*
  if Abs(Frac(X)) >= 0.5 then
    Result := RoundUp(X)
  else
    Result := RoundDn(X);
*)
  Result := Int(X) + Int(Frac(X) * 2);
end;


function Fix(X: Extended): Extended;
// Returns the first integer less than or
// equal to a given number.
//   Int(3.7) = 3          Int(-3.7) = -3
//   Fix(3.7) = 3          Fix(-3.1) = -4
begin
  if (X >= 0) or (Frac(X) = 0) then
    Result := Int(X)
  else
   Result := Int(X) - 1;
end;


function RoundDnX(X: Extended): Extended;
// Returns the first integer less than or
// equal to a given number.
//   RoundDnX(3.7) = 3     RoundDnX(-3.7) = -3
//   RoundDnX(3.7) = 3     RoundDnX(-3.1) = -4
begin
  Result := Fix(X);
end;


function RoundUpX(X: Extended): Extended;
// Returns the first integer greater than or
// equal to a given number.
//   RoundUpX(3.1) = 4     RoundUpX(-3.7) = -3
begin
  Result := Fix(X) + Abs(Sgn(Frac(X)))
end;


function RoundX(X: Extended): Extended;
// Rounds a number "normally", but taking the sign into
// account: if the fractional part is >= 0.5 the number
// is rounded up (see RoundUpX)
// Otherwise, if the fractional part is < 0.5, the
// number is rounded down (see RoundDnX).
//   RoundX(3.5) = 4     RoundX(-3.5) = -3
begin
(*
  if Abs(Frac(X)) >= 0.5 then
    Result := RoundUpX(X)
  else
    Result := RoundDnX(X);
*)
  Result := Fix(X + 0.5);
end;

Rounding to a decimal digit

The functions we've just presented always round to the last integer digit, but sometimes we need to round for example to the second decimal digit or to the thousands, millions or billions. The following function performs a "normal round" taking an extra parameter to indicate the digit to be rounded:

function RoundD(x: Extended; d: Integer): Extended;
// RoundD(123.456, 0) = 123.00
// RoundD(123.456, 2) = 123.46
// RoundD(123456, -3) = 123000
var
  n: Extended;
begin
  n := IntPower(10, d);
  x := x * n;
  Result := (Int(x) + Int(Frac(x) * 2)) / n;
end;
JfControls Library - for Delphi and C++ Builder