Registriert seit: 6. Dez 2005
999 Beiträge
|
AW: tan() von Single, Double, etc.
21. Nov 2017, 10:49
Richtig, aber so sollte eine tand(x)
Funktion mit Argumenten in ° ja auch nicht programmiert werden
Da zum Delphi-Sprachumfang aber nun mal keine tand-Funktion gehört (Delphi 5 kannte noch nicht einmal tan), kann man sich ja bei Bedarf was Passendes selbst programmieren. Mach doch mal einen Vorschlag so wie du es dir vorstellst.
Hier eine vereinfachte Implementation meiner DAMath-Funktion komplett mit Test-Programm
Delphi-Quellcode:
{Test/dev program for tand (c) W.Ehrhardt 2017}
program t_tand;
{$apptype console}
uses
math;
{Vereinfachte Implementation einer tand-Funktion, d.h. Tangens mit }
{Argument in Grad. Achtung: nur bis ca 10^13 = 2^53/180 genau, weil}
{ich nicht noch mehr DAMath-Funktioen einbauen wollte. Compilierbar}
{ab Delphi 6}
{---------------------------------------------------------------------------}
function floord(x: double): double;
{-Return the largest integer <= x}
var
t: double;
begin
t := int(x);
if (x>=0.0) or (x=t) then floord := t
else floord := t - 1.0;
end;
{---------------------------------------------------------------------------}
procedure trig_deg(x: double; var y,z: double; var n: integer; var m45: boolean);
{-Reduce x in degrees mod 90; y=x mod 90, |y|<45. z=x/45, m45 if x is multiple of 45}
const
c45: single = 45.0;
begin
{Basic internal reduction routine mod 90. Use Cody/Waite logic, but no}
{pseudo-multiprecision because 45.0 has only 6 non-zero mantissa bits.}
if x=0.0 then begin
y := 0.0;
z := 0.0;
n := 0;
m45 := true;
end
else begin
z := x/c45;
m45 := (frac(z)=0.0) and (frac(x)=0.0);
y := floord(z);
n := trunc(y - 16.0*floord(y/16.0));
if odd(n) then begin
inc(n);
y := y + 1.0;
end;
n := (n shr 1) and 7;
y := x - y*c45;
end;
end;
{---------------------------------------------------------------------------}
function tand(x: double): double;
{-Return tan(x), x in degrees}
var
y,z: double;
n : integer;
m45: boolean;
begin
trig_deg(x,y,z,n,m45);
if m45 then begin
z := abs(z);
y := sign(x);
case round(4.0*frac(0.25*z)) of
0: tand := 0.0;
1: tand := y;
2: tand := Infinity;
else tand := -y;
end;
end
else begin
z := DegToRad(y);
if odd(n) then tand := -cot(z)
else tand := tan(z);
end;
end;
var
d: integer;
begin
d := 0;
while d<=360 do begin
writeln(d:5, tand(d):25:16);
d := d + 15;
end;
end.
Die Ausgabe ist dann
Code:
0 0.0000000000000000
15 0.2679491924311228
30 0.5773502691896258
45 1.0000000000000000
60 1.7320508075688770
75 3.7320508075688768
90 +Inf
105 -3.7320508075688768
120 -1.7320508075688770
135 -1.0000000000000000
150 -0.5773502691896258
165 -0.2679491924311228
180 0.0000000000000000
195 0.2679491924311228
210 0.5773502691896258
225 1.0000000000000000
240 1.7320508075688770
255 3.7320508075688768
270 +Inf
285 -3.7320508075688768
300 -1.7320508075688770
315 -1.0000000000000000
330 -0.5773502691896258
345 -0.2679491924311228
360 0.0000000000000000
Im getesteten Bereich -10^10 .. 10^10 ist die Genauigkeit ist die gleiche wie bei DAMath
Code:
Test DAMath V0.95 with MP_Arith V1.37.01 (31/32 bit) (c) 2013-2017 W.Ehrhardt
Karatsuba cutoffs: mul/sqr = 16/32
Toom-3, BZ cutoffs: mul/sqr = 32/64, div = 32
Current mp_float default bit precision = 160, decimal precision = 48.2
Machine eps for double = 2.22044604925E-0016
-----------------------------------------------------------------
Test of DAMath.tand
at 10000 random values in [-10000000000.0000000000 .. 10000000000.0000000000]
RMS = 0.38, max rel = 1.25 eps at
x(dbl) = -4.52875830026280448E+0009 = $C1F0DEF5E1C43473
y(dbl) = -1.75054511612172736E+0000 = $BFFC023B987EA53D
y(mpf) = -1.75054511612172687511491287528577674916550040814
-----------------------------------------------------------------
Test of tand (Delphi Praxis)
at 10000 random values in [-10000000000.0000000000 .. 10000000000.0000000000]
RMS = 0.38, max rel = 1.25 eps at
x(dbl) = -4.52875830026280448E+0009 = $C1F0DEF5E1C43473
y(dbl) = -1.75054511612172736E+0000 = $BFFC023B987EA53D
y(mpf) = -1.75054511612172687511491287528577674916550040814
Geändert von gammatester (21. Nov 2017 um 11:20 Uhr)
Grund: Minus bei cot
|
|
Zitat
|