In case you maintain code in older versions of Delphi, be aware that the function tanh
was broken starting in Delphi 7 and only got fixed in Delphi XE2: QualityCentral QualityCentral 56524: tanh function from Delphi 7 till Delphi XE was buggy; XE2 fixed it.
For big inputs, it would just fail, instead of returning 1.
The reason is that in the buggy versions, tanh
got replaced from an old working version into a simple sinh/cosh
, which mathematically is correct, but if your numeric data type has limited accuracy, you need to account for the boundaries where the result fits, but intermediates do not.
the [WayBack] Math.Tanh
Function implements the hyperbolic tangent, for which you can find the definition at Hyperbolic function – Wikipedia: Definitions.
By now it is implemented for all floating point types the same way (only the parameter type changes in each implementation)
function Tanh(const X: Extended): Extended; overload; const MaxTanhDomain = 23; C1of3 = 1/3; CBorder = 1.8145860519450699870567321328132e-5; // 2 ^(-63 / 4) CLn2Div2 = 0.34657359027997265470861606072909; // Ln2 / 2 var y, z: Extended; begin FClearExcept; case TExtendedRec(X).SpecialType of fsPositive, fsNegative: begin z := X; if X < 0 then z := -z; if (z > MaxTanhDomain) then Result := 1.0 else if (z < CBorder) then Result := z - z * z * z * c1of3 else if (z < CLn2Div2) then begin y := ExpMinus1(2*z); Result := y / (2 + y); end else begin y := Exp(2*z); Result := 1 - (2/(y + 1)); end; if X < 0 then Result := -Result; end; else Result := X; end; FCheckExcept; end;
–jeroen