Delphi-PRAXiS
Seite 2 von 3     12 3      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Aus Integer-Wert bestimmte Stelle extrahieren (https://www.delphipraxis.net/95431-aus-integer-wert-bestimmte-stelle-extrahieren.html)

sirius 6. Jul 2007 14:09

Re: Aus Integer-Wert bestimmte Stelle extrahieren
 
Zitat:

Zitat von ibp
@sir vergiss die führende 0 war ein tippfehler beim kloppen auf den nummernblock!

@phreax schau dir mal das beispiel von dax an, die hat nur 4 operationen ;-)

:gruebel: 4 Operationen?

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;

phreax 6. Jul 2007 14:27

Re: Aus Integer-Wert bestimmte Stelle extrahieren
 
Zitat:

Zitat von sirius
:gruebel: 4 Operationen?

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.

dito!

mfg phreax

ibp 6. Jul 2007 15:29

Re: Aus Integer-Wert bestimmte Stelle extrahieren
 
kleiner hinweis...
Zitat:

Zitat von ibp
...10er stelle (hier=2)...

also phreax methode braucht die stellen al 1er,10er,100er... um von den vorliegenden stellen 1,2,3 auf eben solche zu kommen brauchst du eine weitere berechnung, eben die der power :wink:

war vielleicht ein wenig ungünstig beschrieben. also die stellen sind vorhanden als 1,2,3.. usw.

sirius 6. Jul 2007 15:40

Re: Aus Integer-Wert bestimmte Stelle extrahieren
 
Zitat:

Zitat von ibp
war vielleicht ein wenig ungünstig beschrieben. also die stellen sind vorhanden als 1,2,3.. usw.

Meine Funktion beschreibt die Stellen mit 0,1,2,3
Also muss noch ein "dec edx" irgendwo vor @while

ibp 6. Jul 2007 15:56

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?

SirThornberry 6. Jul 2007 16:01

Re: Aus Integer-Wert bestimmte Stelle extrahieren
 
bei der vem von phreax verwendeten Aufruf geht es auch noch so (ohne if):
Delphi-Quellcode:
function GetDigit(Int, Digit: Integer): Integer;
begin
  result := Int mod (Digit * 10) div Digit;
end;
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.

ibp 6. Jul 2007 16:10

Re: Aus Integer-Wert bestimmte Stelle extrahieren
 
Zitat:

Zitat von SirThornberry
...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.

so sollte es eben nicht sein ;-) siehe hier

sirius 6. Jul 2007 16:20

Re: Aus Integer-Wert bestimmte Stelle extrahieren
 
mit kleinen Änderungen
Delphi-Quellcode:
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;
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.
Es geht halt nicht ohne, dass man erst die 10er-Potenzen ausrechnet.

alzaimar 6. Jul 2007 16:49

Re: Aus Integer-Wert bestimmte Stelle extrahieren
 
So würde ich das machen, wenn ich unbedingt die Stelle angeben will...
Delphi-Quellcode:
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;
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.

Macci 31. Aug 2007 13:56

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:
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;
Viele Grüße,
Mac


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:15 Uhr.
Seite 2 von 3     12 3      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz