Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi "Zeichen" im Integer (https://www.delphipraxis.net/84639-zeichen-im-integer.html)

xZise 19. Jan 2007 14:25


"Zeichen" im Integer
 
Wie kann man am schnellsten an die Länge eines Integers kommen, ohne Kommazahlen zu benutzen?

Antigo 19. Jan 2007 14:29

Re: "Zeichen" im Integer
 
meinst du wieviele Ziffern eine Integer Zahl hat?

anzziffern:=length(inttostr(zahl));

aber ist nicht so grad die feine mathematische Art ;)

Christian Seehase 19. Jan 2007 14:30

Re: "Zeichen" im Integer
 
Moin Fabian,

ein integer ist auf einem 32-Bit-System immer 4 Byte lang.

Luckie 19. Jan 2007 14:32

Re: "Zeichen" im Integer
 
Ein Interger ist immer 4 Byte lang. Oder was verstehst du unter "Länge eines Integer"? Ich befrage mal meine Glaskugel und die meint du willst die Anzahl der Ziffern einer Zahl wissen. Bitte vor dem Posten etwas nachdenken, was man eigentlich will und / oder wo konkret das Problem ist. Dann kann man auch die Frage gescheit formulieren. Meist ergibst sich dann schon von selbst die Lösung, wenn man mal etwas darüber nachgedacht hat.

3_of_8 19. Jan 2007 14:33

Re: "Zeichen" im Integer
 
Du meinst die Länge der String-Repräsentation des Integers?

Würd ich so machen:

Delphi-Quellcode:
function GetStrToIntLength(x: Integer): Integer;
begin
  if x<0 then
  begin
    Result:=1;
    x:=abs(x);
  end
    else Result:=0;
  while x>0 do
  begin
    x:=x div 10;
    inc(Result);
  end;
end;
Müsste klappen.

xZise 19. Jan 2007 14:36

Re: "Zeichen" im Integer
 
Okay... Also das meinet ich nicht @ Seehase :D
Ich meinte, wie viele Ziffern ein Integer ohne die führenden Nullen hat.

(Ich hoffe jetzt ist es verständlich :D)

z.B.
12345
wäre dann
5 als Ergebnis

@ Antigo:
So geht es, aber ist es schnell genug?

Muetze1 19. Jan 2007 14:39

Re: "Zeichen" im Integer
 
Zitat:

Zitat von xZise
@ Antigo:
So geht es, aber ist es schnell genug?

Das musst du uns sagen, ob es für deine Zwecke schnell genug ist. Vor allem hängt es von der durchschnittlichen Grösse deiner Zahlen ab, ob sich nun eine Divisionsschleife eher lohnt als eine String-Wandlung.

Vor allem: wozu brauchst du diese Information, wenn man fragen darf?

Jürgen Thomas 19. Jan 2007 14:42

Re: "Zeichen" im Integer
 
Tut mir leid, ich verstehe überhaupt nicht, was Du willst - vor allem, weil Du bei integer auf einmal von Kommazahlen sprichst. Du bist ja nicht "neu im Geschäft"; deshalb nehme ich an, Du meinst nicht:
Delphi-Quellcode:
iLaenge := SizeOf(integer);
Folgendes dürfte ziemlich langsam sein:
Delphi-Quellcode:
iLaenge := Length(IntToStr(iZahl));
Ich würde es vermutlich so machen:
Delphi-Quellcode:
function AnzahlZiffern(const iZahl: int): integer;
var i0: integer;
begin
  Result := 1;
  i0 := iZahl div 10;
  while (i0 >= 0)
  do begin
    Inc(Result);
    i0 := i0 div 10;
  end;
end;
Ich vermute, dass einer der Fachleute für ASM oder Bit-Manipulation eine schnellere Lösung kennt. Jürgen

PS. Bitte nicht sauer sein, wenn ich mit C#-Schreibweisen durcheinander gekommen bin.

PS2. Das war ja klar, dass ich langsam bin; aber meine Antwort ist noch nicht überflüssig.

Eichhoernchen 19. Jan 2007 14:42

Re: "Zeichen" im Integer
 
wie wärs mit dem 10er Logarithmus?


Delphi-Quellcode:
uses math;

{...}

function GetDigitLength(x: integer): integer;
begin
 if x <> 0 then
   result := trunc(1+Log10(abs(x)));
end;

xZise 19. Jan 2007 14:54

Re: "Zeichen" im Integer
 
Zitat:

Zitat von Jürgen Thomas
Tut mir leid, ich verstehe überhaupt nicht, was Du willst - vor allem, weil Du bei integer auf einmal von Kommazahlen sprichst.

Wo ist das Problem? Ich will die Anzahl der Ziffern ohne führenden Nullen einer Ganzzahl.
Und bei der Berechnung möchte ich auf Kommazahlen verzichten.

Zitat:

Zitat von Jürgen Thomas
Du bist ja nicht "neu im Geschäft"; deshalb nehme ich an, Du meinst nicht:
Delphi-Quellcode:
iLaenge := SizeOf(integer);

Sry, aber mit der SizeOf Methode arbeite ich eigentlich nicht.
Würde es mir die Bitgröße (= 4 Byte) wiedergeben=?

Folgendes dürfte ziemlich langsam sein:
Delphi-Quellcode:
iLaenge := Length(IntToStr(iZahl));
Zitat:

Zitat von Jürgen Thomas
Ich würde es vermutlich so machen:
Delphi-Quellcode:
function AnzahlZiffern(const iZahl: int): integer;
var i0: integer;
begin
  Result := 1;
  i0 := iZahl div 10;
  while (i0 >= 0)
  do begin
    Inc(Result);
    i0 := i0 div 10;
  end;
end;

Ist ja fast 3 of 8 Methode.

Zitat:

Zitat von Jürgen Thomas
Ich vermute, dass einer der Fachleute für ASM oder Bit-Manipulation eine schnellere Lösung kennt.

Da sich bisher niemand dazu geäußert hat... Ist es wahrschienlich eure (deine und 3 of 8) Lösung!

Zitat:

Zitat von Jürgen Thomas
PS. Bitte nicht sauer sein, wenn ich mit C#-Schreibweisen durcheinander gekommen bin.

Außer die Klammern in der "while"-Zeile sieht da nichts falsch aus... (Wobei die Klammern kein Fehler sind, aber eigentlich doch in c# Pflicht sind...)

Zitat:

Zitat von Jürgen Thomas
PS2. Das war ja klar, dass ich langsam bin; aber meine Antwort ist noch nicht überflüssig.

;)

Ich sehe schon... Ich werde das mit den Methoden versuchen... und Testen wer schnell ist und wer nicht...

3_of_8 19. Jan 2007 14:57

Re: "Zeichen" im Integer
 
Ich nehme mal an, auch mit Assembler wird es nicht recht viel schneller gehen. Das einzige, was man hier ausnutzen kann, ist diese Schweinerei mit cdq, bringt aber auch nicht recht viel, wenn überhaupt was.

Delphi-Quellcode:
function NumberLength(x: Integer): Integer;
asm
  push ebx
  mov ebx, 10
  cdq
  mov ecx, edx
  and ecx, 1
  xor eax, edx
  sub eax, edx
  @loop:
  and eax, eax
  jz @endloop
  mov edx, 0
  div ebx
  add ecx, 1
  jmp @loop
  @endloop:
  mov eax, ecx
  pop ebx
end;

JasonDX 19. Jan 2007 15:58

Re: "Zeichen" im Integer
 
Ich wuerde sagen, die staendige Division ist eine unnoetige Bremse, die man nicht zwingend braucht.
Algorithmisch gesehen sollte das die schnellste Variante sein:
Delphi-Quellcode:
function DecIntLength(x: integer): byte;
const
  m: packed array[0..9] of integer = ($A, $64, $3E8, $2710, $186A0, $F4240, $989680, $5F5E100, $3B9ACA00, $0);
asm
   MOV EAX, x
   MOV ESI, m
   CDQ
   XOR EAX, EDX
   AND EDX, 1
   ADD EAX, EDX
@@loopstart:
   INC DL
   MOV EBX, [ESI]
   TEST EBX, EBX
   JZ loopend
   CMP EBX, EAX
   JA loopend
   ADD ESI, 4
   JMP loopstart
@@loopend:
   MOV AL, DL
end;
Ich hab leider keinen Delphicompiler installiert, aber ich sehe eigentlich keinen grund, warums nich laufen sollte ;)

greetz
Mike

[Edit] and is schneller als sets, also her damit ;)
[Edit2] und den test brauchma auch ned... hoff ich zumindest mal *g*

xZise 19. Jan 2007 18:02

Re: "Zeichen" im Integer
 
Und das ganze jetzt für den Int64 :D

Ein Problem in deinem Code :D
Zitat:

[Pascal Fehler] uMain.pas(6): E2107 Operandengröße stimmt nicht überein
Delphi-Quellcode:
MOV ESI, m

3_of_8 19. Jan 2007 19:01

Re: "Zeichen" im Integer
 
Jason, warum schreibst du statt $A, $64,... nicht einfach 10, 100,...? Zur Verwirrung? :lol:

JasonDX 19. Jan 2007 19:41

Re: "Zeichen" im Integer
 
Zitat:

Zitat von 3_of_8
Jason, warum schreibst du statt $A, $64,... nicht einfach 10, 100,...? Zur Verwirrung? :lol:

Nein, weil ich das array eigentlich mal in den Code-Block schieben wollte, damit ich nicht auf ein Sprach-abhaengiges array zurueckgreifen haette muessen. Hat aber nicht zu ganz geklappt, und hab aus Gewohnheit die Hex-Werte kopiert... Wenn ich Leute Verwirren will, sieht das anders aus ;)
Na ja, das mit dem Array hatte dann auch zur folge, dass dann das geschriebene nichmehr kompiliert... warum auch immer Delphi was dagegen hat, nen Zeiger in ein 32-Bit-Register zu schreiben :gruebel:

Egal, es geht auch ohne assembler:
Delphi-Quellcode:
function DecIntLength(x: integer): byte;
const
  m: packed array[0..9] of integer = (10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 0);
var
  i: byte;
begin
  result := 0;
  i := 0;
  if (x < 0) then
  begin
    inc(result);
    x := -x;
  end;
  repeat
    inc(i);
  until ((m[i] = 0) or (m[i] > x))
  inc(result, i);
end;
Zitat:

Zitat von xZise
Und das ganze jetzt für den Int64 :D

Einfach alle integers durch int64 ersetzen, und folgendes fuer m nehmen:
Delphi-Quellcode:
m: packed array[0..17] of integer = (10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, 1000000000000000, 10000000000000000, 100000000000000000, 0);
Wie gesagt: nicht probiert...

greetz
Mike

jmd anders 19. Jan 2007 23:46

Re: "Zeichen" im Integer
 
ich hab mal ein bißchen rumgetestet, auch mit assembler, bisher aber nur für 32bit integer.
Delphi-Quellcode:
function InlineAsm(x:integer) : integer;
const e=1;
      z=10;
      h=100;
      t=1000;
     zt=10000;
     ht=100000;
      m=1000000;
     zm=10000000;
     hm=100000000;
     md=1000000000;
    zmd=10000000000;
asm
  MOV EDX, EAX
  JMP @Ret1

  @Ret1            :
    CMP EDX,z
    JAE @Ret10
    MOV EAX, 1
    JMP @Ende;
  @Ret10           :
    CMP EDX,h
    JAE @Ret100
    MOV EAX, 2
    JMP @Ende;
  @Ret100          :
    CMP EDX,t
    JAE @Ret1000
    MOV EAX, 3
    JMP @Ende;
  @Ret1000         :
    CMP EDX,zt
    JAE @Ret10000
    MOV EAX, 4
    JMP @Ende;
  @Ret10000       :
    CMP EDX,ht
    JAE @Ret100000;
    MOV EAX, 5
    JMP @Ende;
  @Ret100000       :
    CMP EDX,m
    JAE @Ret1000000
    MOV EAX, 6
    JMP @Ende;
  @Ret1000000      :
    CMP EDX,zm
    JAE @Ret10000000
    MOV EAX, 7
    JMP @Ende;
  @Ret10000000     :
    CMP EDX,hm
    JAE @Ret100000000
    MOV EAX, 8
    JMP @Ende;
  @Ret100000000    :
    CMP EDX,md
    JAE @Ret100000000
    MOV EAX, 9
    JMP @Ende;
  @Ret1000000000    :
    MOV EAX, 10
    JMP @Ende;

 @Ende :
end;
das ist dabei rausgekommen, sehr ähnlich zu jason's asm funktion, nur ohne irgendwelche schleifen.
ich hab jason's asm funktion nicht getestet, aber seine delphi funktion, die war extrem schnell(7-8mal schneller als die asm funktion von 3_of_8).
ich hatte das gefühl, dass meine funktion einen tick schneller ist als die delphi funktion von jason(ich glaub nicht mal 1%)


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:43 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 by Thomas Breitkreuz