3
votes

I have the following function in my program and it is giving me an EInvalidOp (Invalid Floating Point Operation):

function TMyProgram.GetVal(A, B, C, D, E: double): double;

begin

  Result := A/Power((C - D)/(D - B), 1/E);

end;

The values of the parameters are:

A: 320.068, B: 84.46, C: 91.632, D: 24.15, E: 11

Excel gives me a result of -316.815, but Delphi is giving me an error when I execute this function.

2
Interesting. The docs say "for fractional exponents, base must be greater than 0". I wonder why.Sertac Akyuz
That would involve getting into complex numbers, I suppose (for example, -1 ^ 0.5 is the square root of -1, which is really an imaginary number), so I get what the "docs" say, but I wonder how Excel solves this problem.Serge
Excel is doing an absolute on the base and then negating the result. A number of online calculators do the same thing.Graymatter
You have to decide what answer you want. What do you want this calculation to return? Perhaps an exception is correct.David Heffernan
@DavidHeffernan There's some support involving Variants - docwiki.embarcadero.com/Libraries/XE6/en/System.VarCmplx. There's also a sample with a bit more usable setup but I'm assuming that if it's a sample it's unsupported: docwiki.embarcadero.com/CodeExamples/XE6/en/….alcalde

2 Answers

-1
votes

-316.81520613

Thats what i get with the power2 function by Jack Lyle.

look here for full code power2

{** 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 }
    ... // see the link to full code

  END; { FUNCTION Pow }
1
votes

I did a bit more research. The problem is raising a negative base to a fractional exponent. In your particular case you can use mathematical identity to get around it by doing the following:

function TMyProgram.GetVal(A, B, C, D: Double; E: Integer): double;
begin
  if Odd(E) and ((C - D)/(D - B) < 0) then
    Result := A/-Power(Abs((C - D)/(D - B)), 1/E)
  else
    Result := A/Power((C - D)/(D - B), 1/E);
end;

This only works when E is an odd number.