Zitat von
3_of_8:
Abgesehen von der Heron-Formel gäbe es noch diese nicht ganz so rechenintensive Möglichkeit:
(sqrt ist IIRC langsamer als sin)
@3_of_8 :
Da ist Intel aber ganz anderer Meinung.
FSIN benötigt 160-200 Takte
FSQRT benötigt 23 Takte (Single), 38 Takte (Double), 43 Takte (Extended)
Ich hab das mal getestet
Deine Version : f1:=Sin(alpha)*b*c/2;
Eine andere Version : f2:=Sqrt(4*Sqr(a)*Sqr(b) - Sqr((Sqr(a) + Sqr(b) - Sqr(c)))) / 4;
Deine Version = 344 Takte
Andere Version = 292 Takte
Und beides durch
ASM-Funktionen optimiert
Deine Version = 296 Takte
Andere Version = 200 Takte
Zu beachten ist noch, daß beim Test der Winkel bereits in
Rad vorliegt und nicht, wie bei Aufgabenstellungen üblich, in Grad.
Das bringt dann auch noch ein paar Takte auf die Waage.
Und zum Nachprüfen hier die komplette Test-Prozedur :
Delphi-Quellcode:
PROCEDURE TMain.Test;
var a,b,c,alpha,f1,f2,f3,f4:extended; t0,t1,t2,t3,t4:int64; i:integer;
FUNCTION TimeStamp:int64;
asm
rdtsc
end;
FUNCTION Surface1(
var alpha,b,c:extended):extended;
// Sinus-Version
const two:integer=2;
asm
fld tbyte [edx]
// b
fld tbyte [ecx]
// c
fld tbyte [eax]
// alpha
fsin
fmulp
fmulp
fidiv two
end;
FUNCTION Surface2(
var a,b,c:extended):extended;
// andere Version
const four:integer=4;
asm
fld tbyte [eax]
// a
fmul st,st
// st0=Sqr(a)
fld tbyte [edx]
// b
fmul st,st
// st0=Sqr(b), st1=Sqr(a)
fld tbyte [ecx]
// c
fmul st,st
// st0=Sqr(c), st1=Sqr(b), st2=Sqr(a)
fchs
// st0=-Sqr(c), st1=Sqr(b), st2=Sqr(a)
fadd st,st(1)
// st0=Sqr(b)-Sqr(c), st1=Sqr(b), st2=Sqr(a)
fadd st,st(2)
// st0=Sqr(a)+Sqr(b)-Sqr(c), st1=Sqr(b), st2=Sqr(a)
fmul st,st
// st0=Sqr(Sqr(a)+Sqr(b)-Sqr(c)), st1=Sqr(b), st2=Sqr(a)
fxch st(2)
// st0=Sqr(a), st1=Sqr(b), st2=Sqr(Sqr(a)+Sqr(b)-Sqr(c))
fimul four
// st0=4*Sqr(a), st1=Sqr(b), st2=Sqr(Sqr(a)+Sqr(b)-Sqr(c))
fmulp
// st0=4*Sqr(a)*Sqr(b), st1=Sqr(Sqr(a)+Sqr(b)-Sqr(c))
fsubrp
// st0=4*Sqr(a)*Sqr(b)-Sqr(Sqr(a)+Sqr(b)-Sqr(c))
fsqrt
// st0=Sqrt(4*Sqr(a)*Sqr(b)-Sqr(Sqr(a)+Sqr(b)-Sqr(c)))
fidiv four
// st0=Sqrt((4*Sqr(a)*Sqr(b)-Sqr(Sqr(a)+Sqr(b)-Sqr(c))))/4
end;
begin
a:=3;
b:=4;
c:=4.5;
alpha:=0.71217178712617798;
// Rad
t1:=High(int64);
t2:=High(int64);
t3:=High(int64);
t4:=High(int64);
for i:=1
to 10
do begin
// Sinus-Version
t0:=Timestamp;
f1:=Sin(alpha)*b*c/2;
t0:=Timestamp-t0;
if t0<t1
then t1:=t0;
// andere Version
t0:=Timestamp;
f2:=Sqrt(4*Sqr(a)*Sqr(b) - Sqr((Sqr(a) + Sqr(b) - Sqr(c)))) / 4;
t0:=Timestamp-t0;
if t0<t2
then t2:=t0;
// Sinus-Version in ASM
t0:=Timestamp;
f3:=Surface1(alpha,b,c);
t0:=Timestamp-t0;
if t0<t3
then t3:=t0;
// andere Version in ASM
t0:=Timestamp;
f4:=Surface2(a,b,c);
t0:=Timestamp-t0;
if t0<t4
then t4:=t0;
end;
ShowMessage('
F1='+FloatToStr(f1)+'
Ticks='+IntToStr(t1)+'
(Sinus)'#13+
'
F2='+FloatToStr(f2)+'
Ticks='+IntToStr(t2)+'
(andere)'#13+
'
F3='+FloatToStr(f3)+'
Ticks='+IntToStr(t3)+'
(Sinus ASM)'#13+
'
F4='+FloatToStr(f4)+'
Ticks='+IntToStr(t4)+'
(andere ASM)');
end;