Delphi and the Power Function

By: Charles Calvert

Abstract: This article talks about Delphi and the Power function

Overview

This article provides an overview of raising a number to some arbitrary power in a Delphi program.

Discussion

Some computer languages have a power operator that raises a value to a power. In Fortran for example the operator is ** as in 2.0**3.0 which returns 8.0. Ada also uses the ** notation and Basic uses the ^ symbol. For some reason, Pascal and C do not include this operator. That is particularly odd because Algol60, which was the ancestor of both, did have a power operator, (^). For years, the solution in Pascal has been to use a function usually given as

function Power(x, y :extended) : extended; begin result := exp(y*ln(x)); end;

The problem with that easy answer is that this function will fail (raise an exception) for a negative base value.

Base

Exponent

Simple

Delphi

Jack

Excel

1.0E-16

1.0

1.0E-16

1.0E-16

0.0

1.0E-16

2.0

1.0E-16

1.0

1.0

1.0

1.0

2.0

2.0

4.0

4.0

4.0

4.0

3.0

3.0

27.0

27.0

27.0

27.0

-3.0

2.0

Exception

9.0

9.0

9.0

-3.0

3.0

Exception

-27.0

-27.0

-27.0

3.0

-3.0

0.0370370...

0.0370370...

0.0370370...

0.0370370...

-3.0

-3.0

Exception

-0.0370370...

-0.0370370...

-0.0370370...

pi

pi

36.462159

36.462159

36.462159

36.462159

The function can be made to work if all the special cases are considered.

{** A power function from Jack Lyle. Said to be more powerful than the
    Pow function that comes with Delphi. }
function Power2(Base, Exponent : Double) : Double;
{ raises the base to the exponent }
  CONST
    cTiny = 1e-15;

  VAR
    Power : Double; { Value before sign correction }

  BEGIN
    Power := 0;
    { Deal with the near zero special cases }
    IF (Abs(Base) < cTiny) THEN BEGIN
      Base := 0.0;
    END; { IF }
    IF (Abs(Exponent) < cTiny) THEN BEGIN
      Exponent := 0.0;
    END; { IF }

    { Deal with the exactly zero cases }
    IF (Base = 0.0) THEN BEGIN
      Power := 0.0;
    END; { IF }
    IF (Exponent = 0.0) THEN BEGIN
      Power := 1.0;
    END; { IF }

    { Cover everything else }
    IF ((Base < 0) AND (Exponent < 0)) THEN
        Power := 1/Exp(-Exponent*Ln(-Base))
    ELSE IF ((Base < 0) AND (Exponent >= 0)) THEN
        Power := Exp(Exponent*Ln(-Base))
    ELSE IF ((Base > 0) AND (Exponent < 0)) THEN
        Power := 1/Exp(-Exponent*Ln(Base))
    ELSE IF ((Base > 0) AND (Exponent >= 0)) THEN
        Power := Exp(Exponent*Ln(Base));

    { Correct the sign }
    IF ((Base < 0) AND (Frac(Exponent/2.0) <> 0.0)) THEN
      Result := -Power
    ELSE
      Result := Power;
  END; { FUNCTION Pow }

This function, labeled Jack in the table above, returns the correct values if you will allow that 1e-16 is the same as 0.0.

Delphi 4 added a standard math unit to the Borland Pascal distribution. That unit includes a power function and an IntPower function. For some reason, they are not overloaded. The Delphi power function also checks the special cases (in much less verbose code than mine) and returns the correct answer.

So, for Delphi versions 4 and later use the math units Power function. For older versions of Delphi or Turbo Pascal use the Pow function given above. Do not use the simple Power function if you expect to ever see a negative base as input.

Summary

In Delphi 4 and later, use the Power function from the math unit. In earlier versions, use the Pow function given below.

 

 



Server Response from: ETNASC04