![]() |
Re: Aus Integer-Wert bestimmte Stelle extrahieren
Zitat:
Intpower und Round sind Funktionen. Besonders Intpower, rechnet nicht nur in der FPU, was alleine schon länger dauert, sondern dort auch noch ne Menge Operationen. Und Round benutzt auch die interne FPU "round"-Funktion. Edit: Die ASM-Variante
Delphi-Quellcode:
function getdigit(zahl,stelle:integer):integer;
asm push ebx xor ecx,ecx inc ecx xor ebx,ebx mov bl,10 @while: dec edx jl @endwhile imul ecx,10 jmp @while @endwhile: cdq div ecx cdq div ebx mov eax,edx pop ebx end; |
Re: Aus Integer-Wert bestimmte Stelle extrahieren
Zitat:
mfg phreax |
Re: Aus Integer-Wert bestimmte Stelle extrahieren
kleiner hinweis...
Zitat:
war vielleicht ein wenig ungünstig beschrieben. also die stellen sind vorhanden als 1,2,3.. usw. |
Re: Aus Integer-Wert bestimmte Stelle extrahieren
Zitat:
Also muss noch ein "dec edx" irgendwo vor @while |
Re: Aus Integer-Wert bestimmte Stelle extrahieren
@sirius da ich leider des asm nicht mächtig bin, könntest du es mir bitte erklären was da genau passiert?
|
Re: Aus Integer-Wert bestimmte Stelle extrahieren
bei der vem von phreax verwendeten Aufruf geht es auch noch so (ohne if):
Delphi-Quellcode:
Wenn man also von 101125 die 5 haben will muss man 1 übergeben, wenn man die 2 haben will 10, wenn man die 0 haben will 10000.
function GetDigit(Int, Digit: Integer): Integer;
begin result := Int mod (Digit * 10) div Digit; end; |
Re: Aus Integer-Wert bestimmte Stelle extrahieren
Zitat:
![]() |
Re: Aus Integer-Wert bestimmte Stelle extrahieren
mit kleinen Änderungen
Delphi-Quellcode:
Bis endwhile ist die Vorbereitung dass aus 1,2,3,4 -->1,10,100,1000 wird. Ab dem CDQ macht die funktion das, was Sirthornberry auch macht.
function getdigit(zahl,stelle:integer):integer;
{ in zahl --> eax stelle --> edx out result <-- eax } asm push ebx //ebx auf den Stack retten xor ecx,ecx //ecx löschen inc ecx //ecx auf 1 setzen mov ebx,10 //ebx auf 10 setzen @while: //nur ein Label für Sprungziele dec edx //edx um 1 erniedrigen jng @endwhile //wenn edx nicht größer als 0 nach @endwhile springen imul ecx,10 //ecx mit 10 multiplizieren jmp @while //nach @while springen @endwhile: cdq //convert DWord-->QWord (Division vorbereiten) div ecx //division von eax/ecx --> ganzzahliger Anteil in eax; Rest in edx cdq //dasselbe nochmal div ebx //division von eax/ebx (Rest steht wieder in edx) mov eax,edx //edx nach eax(=Result) pop ebx //gerettetes Register wieder herstellen end; Es geht halt nicht ohne, dass man erst die 10er-Potenzen ausrechnet. |
Re: Aus Integer-Wert bestimmte Stelle extrahieren
So würde ich das machen, wenn ich unbedingt die Stelle angeben will...
Delphi-Quellcode:
Das dürften -grob geschätzt- 2 Operationen und ein paar Vergleiche (Case of) sein. Schneller ginge es(?) nur mit einer Sprungtabelle. Weiterhin spart man eine Multiplikation ggü der vorherigen Version.
Function GetDigit (anInteger, aDigit : Integer) : Integer;
Begin Case aDigit of 1 : Result := anInteger Mod 10; 2 : Result := (anInteger Div 10) Mod 10; 3 : Result := (anInteger Div 100) Mod 10; 4 : Result := (anInteger Div 1000) Mod 10; 5 : Result := (anInteger Div 10000) Mod 10; 6 : Result := (anInteger Div 100000) Mod 10; 7 : Result := (anInteger Div 1000000) Mod 10; 8 : Result := (anInteger Div 10000000) Mod 10; 9 : Result := (anInteger Div 100000000) Mod 10; else Result := 0 // Mehr Stellen hat ein INTEGER nicht (und wenn doch: einfach erweitern) End End; |
Re: Aus Integer-Wert bestimmte Stelle extrahieren
Hallo,
hab gerade diesen Thread gelesen. Mit meiner Lösung ist eine superschnelle Berechnung möglich. Vielleicht braucht es ja noch jemand ;-)
Delphi-Quellcode:
function GetDecimalDigit(number,digit:Integer):ShortInt;
asm MOV ECX, @table.Pointer[EDX*4] CDQ IDIV ECX CDQ MOV ECX, 10 IDIV ECX MOV AL, DL {Die folgenden 3 Zeilen können einkommentiert werden, wenn NEGATIVE Zahlen auch unterstützt werden sollen, so dass das Ergebnis trotzdem eine positive Zahl ist. Also wenn z.B. GetDecimalDigit(-3210,1) = 1 sein soll, und NICHT GetDecimalDigit(-3210,1) = -1, NUR dann die 3 folgenden Zeilen einkommentieren! (Geschwindigkeitsverlust von ca. 12% !!) } //CBW //XOR AL, AH //SUB AL, AH RET @table: DD 1,10,100,1000,10000,100000 DD 1000000, 10000000, 100000000, 1000000000 end; Zum Testen kann folgender Code verwendet werden.
Delphi-Quellcode:
Viele Grüße,
procedure TForm1.Button1Click(Sender: TObject);
var a,b,c:int64;i:integer; begin QueryPerformanceFrequency(a); QueryPerformanceCounter(b); for i:=1 to 10000000 do GetDecimalDigit(6543210,3); QueryPerformanceCounter(c); ShowMessage('10 Mio. Berechnungen benötigten: '+ IntToStr((c - b) * 1000 div a) + ' Millisekunden, ' + 'eine Berechnung benötigte: '+ IntToStr((c - b) * 100 div a) + ' Nanosekunden.'); end; Mac |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:36 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