AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

n über k - berechnen!?

Ein Thema von Plague · begonnen am 16. Jan 2005 · letzter Beitrag vom 21. Jan 2010
 
Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.087 Beiträge
 
Delphi XE2 Professional
 
#16

Re: n über k - berechnen!?

  Alt 16. Jan 2010, 11:35
Zitat von Wolfgang Mix:
Und wie würdest Du das heute machen?
Ich hab das mal komplett in ASM hingestolpert.
Wesentliche Änderungen:
1) wenn N-K < K ist wird NK(N,K) als NK(N,N-K) ausgeführt.
2) die Routine die versucht Faktoren durch Kürzen zu eleminieren, arbeitet vollständig in der FPU

Besonders bei großen N und großen K ergeben sich durch (1) erhebliche Verbesserungen gegenüber der ursprünglichen Version.
Code:
NK(50,10)      1000000 x ausgeführt = 390 ms (ursprünglich 1200 ms)
NK(25000,24999)      1 x ausgeführt =  0 ms (ursprünglich 1800 ms)
Bei Fehlern wird als Ergebnis NaN zurückgegeben.
Andere Fehler wie Überschreitung des Rechenbereiches oder Out of Memory werden nicht abgefangen.
Delphi-Quellcode:
FUNCTION NK(n,k:integer):extended;
asm
               test eax,eax
               js @ReturnNan // n<0, Fehler
               test edx,edx
               js @ReturnNan // k<0, Fehler
               je @Return1 // k=0, Result=1
               mov ecx,eax
               sub ecx,edx // d:=n-k
               js @Return0 // k>n, Result=0
               je @Return1 // k=n, Result=1
               cmp ecx,edx // if d<k then k:=d
               jae @1
               mov edx,ecx
@1: cmp edx,1
               jne @2 // k<>1
@ReturnN: push eax
               fild dword [esp]
               pop eax
               jmp @End
@ReturnNan: lea eax,@Nan.Pointer[eax]
               fld tbyte [eax]
               jmp @End
@NaN: dw 0,0,0,$C000,$FFFF
@Return0: fldz
               jmp @End
@Return1: fld1
               jmp @End
               //---------------------------------------------------------------
@2: push ebx // EBX retten
               // Platz für k Integers auf Stack reservieren
               lea ecx,[edx*4]
               sub esp,ecx
               // n, n-1, n-2, ... n-k+1 auf Stack legen
               sub ecx,4
@Loop1: mov [esp+ecx],eax
               sub eax,1
               sub ecx,4
               jnc @Loop1
               //---------------------------------------------------------------
               // alle k gegen n aus liste kürzen, ggfs. in st aufmultiplizieren
               //---------------------------------------------------------------
               push edx // k
               fld1
               fld1
               fild dword [esp] // st0=k, st1=Const 1, st2=Produkt(k)
               lea eax,[edx-1]
@Loop2: mov ecx,edx // Index Listenende
@Loop3: // prüfen, ob ein Wert aus der Liste durch k teilbar ist
               fild dword [esp+ecx*4] // st0=n
               fdiv st,st(1) // st0=n/k
               fld st // dto
               frndint // st0=Int(n/k)
               fcomip st,st(1)
               je @Divisible // n durch k teilbar
               ffree st(0)
               fincstp
               sub ecx,1
               jne @Loop3
               fmul st(2),st // k zu st(1) multiplizieren
@NextK: fsub st,st(1) // k:=k-1
               sub eax,1
               jne @Loop2 // weiter bis k=1
               jmp @Finish
@Divisible: // Ist teilbar. wenn quotient=1 dann n aus Liste entfernen,
               // sonst Quotient in Liste
               fcomi st,st(2)
               je @Quotient1 // Quotient ist 1
               fistp dword [esp+ecx*4] // Quotient in Liste
               jmp @NextK
@Quotient1: // Qoutient=1, n aus Liste entfernen
               ffree st(0)
               fincstp
               mov ebx,[esp+edx*4]
               mov [esp+ecx*4],ebx
               sub edx,1
               jmp @NextK
@Finish: // Alle n aus Liste aufmultiplizieren
               fcomp // k vom FPU-Stack nehmen
@Loop4: fimul dword [esp+edx*4]
               sub edx,1
               jne @Loop4
               // Und durch Produkt(k) dividieren
               fdivrp
               // Liste vom Stack nehmen
               pop edx
               lea esp,[esp+edx*4]
               pop ebx
@End:
end;
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
 


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:38 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz