Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Zahl in einzelne Stellen zerlegen ohne Stringkonvertierung! (https://www.delphipraxis.net/133112-zahl-einzelne-stellen-zerlegen-ohne-stringkonvertierung.html)

richard_boderich 25. Apr 2009 23:34


Zahl in einzelne Stellen zerlegen ohne Stringkonvertierung!
 
Hallo zusammen!

Ich hätte da mal eine Frage an die Runde. Ich habe eine 3- stellige Zahl sagen wir mal die z.B. die "123".
Ich möchte diese Zahl jetzt gerne zerlegen. und zwar in ihre 1-ner , 10-ner und 100-ter Stelle. Undzwar wenn möglich
elegant und ohne Stringconvertierung (und Zerlegung in einzelne Chars).

Also so...

123 = 1 100'er Stelle
= 2 10' Stelle
= 3 1' Stelle

Das kann man ja auch so ausdrücken

-> 1*10^2 + 2*10^1 + 3*10^0

so kann man die Zahl erzeugen, aber ich habe grad gar keine Idee wie man zurückrechnen könnte.
Hat da jemand eine Idee?

Dax 26. Apr 2009 00:18

Re: Zahl in einzelne Stellen zerlegen ohne Stringkonvertieru
 
Mal nicht direkt in Delphi, sonder eher funktional. Aber das Prinzip sollte klar werden ;)
Code:
function toDigits (0) = []
function toDigits (number) = concat(toDigits (number / 10), listOf(number mod 10))

DeddyH 26. Apr 2009 08:46

Re: Zahl in einzelne Stellen zerlegen ohne Stringkonvertieru
 
Spontan fallen mir da auch 2 Möglichkeiten ein:
Delphi-Quellcode:
function Stellenwert(Zahl: integer; Stelle: byte): integer;
begin
  Result := trunc(Zahl / Power(10,Pred(Stelle))) mod 10;
  //oder
  Result := trunc(frac(Zahl / Power(10,Stelle)) * 10);
end;
Stelle ist dann "von rechts" anzugeben, also 1 für die 1er-Stelle, 2 für die 10er-Stelle usw.

alzaimar 26. Apr 2009 09:25

Re: Zahl in einzelne Stellen zerlegen ohne Stringkonvertieru
 
Und sukkzessives Zerteilen geht so:
Delphi-Quellcode:
Function NumberToDigits (aNumber : Cardinal) : TByteArray;
Var
  n : Integer;

Begin
  n := 0;
  SetLength (Result, 10);
  While aNumber <> 0 do Begin
    Result[n] := aNumber mod 10;
    aNumber := aNumber div 10;
    Inc (n);
  End;
  SetLength (Result, n + 1);
End;
..
// Beispiel
Var
  B : TByteArray;

Begin
  B := NumberToDigits (1234); // --> B = (4,3,2,1), also B[0] = 4, B[1] = 3 usw
Dann hast Du in einem Abwasch gleich die ganze Zahl unterteilt.

DeddyH 26. Apr 2009 09:29

Re: Zahl in einzelne Stellen zerlegen ohne Stringkonvertieru
 
Angeber :tongue:. Aber dann würde ich das Array zumindest als Parameter übergeben, um dem Grundsatz genüge zu tun, dass man Speicher auf der Ebene freigeben soll, auf der er angefordert wurde.

himitsu 26. Apr 2009 10:01

Re: Zahl in einzelne Stellen zerlegen ohne Stringkonvertieru
 
jetzt könnte man noch auf ASM umsteigen (IDIV = DIV + MOD zugleich)

PS: wegen des Speichers ... da kümmert sich Delphi drum, also isses "egal", da du dich nicht ums Freigeben kümmern mußt :angel2:

Amateurprofi 26. Apr 2009 10:54

Re: Zahl in einzelne Stellen zerlegen ohne Stringkonvertieru
 
Zitat:

Zitat von alzaimar
Und sukkzessives Zerteilen geht so:
Delphi-Quellcode:
Function NumberToDigits (aNumber : Cardinal) : TByteArray;
Var
  n : Integer;

Begin
  n := 0;
  SetLength (Result, 10);
  While aNumber <> 0 do Begin
    Result[n] := aNumber mod 10;
    aNumber := aNumber div 10;
    Inc (n);
  End;
  SetLength (Result, n + 1);
End;
..
// Beispiel
Var
  B : TByteArray;

Begin
  B := NumberToDigits (1234); // --> B = (4,3,2,1), also B[0] = 4, B[1] = 3 usw
Dann hast Du in einem Abwasch gleich die ganze Zahl unterteilt.


@alzaimar:
In der letzten Zeile von NumberToDigits sollte es wohl besser heißen
Delphi-Quellcode:
SetLength (Result, n);

richard_boderich 26. Apr 2009 11:11

Re: Zahl in einzelne Stellen zerlegen ohne Stringkonvertieru
 
@alzaimar

Leider bekomme ich unter Delphi 7 die Fehlermeldung inkompatible Typen bei den Setlength Zuweisungen?!

himitsu 26. Apr 2009 11:23

Re: Zahl in einzelne Stellen zerlegen ohne Stringkonvertieru
 
nimm mal statt TByteArray ein TByteDynArray :angel:


[add]
Delphi-Quellcode:
Uses Types; // für TByteDynArray

Function NumberToDigits(Number: Cardinal): TByteDynArray;
  Var n: Integer;

  Begin
    SetLength(Result, 10);
    n := 0;
    ASM
      PUSH EDI
      MOV  EDI, &Result
      MOV  EDI, [EDI]
      MOV  ECX, 10
      MOV  EAX, &Number
      @@Loop:
      XOR  EDX, EDX
      IDIV ECX
      MOV  [EDI], DL
      INC  EDI
      INC  &n
      TEST EAX, EAX
      JNZ  @@Loop
      POP  EDI
    End;
    SetLength(Result, n);
  End;

richard_boderich 26. Apr 2009 12:10

Re: Zahl in einzelne Stellen zerlegen ohne Stringkonvertieru
 
besten Dank himi! Es funktionopelt prächtig :)

alzaimar 26. Apr 2009 14:10

Re: Zahl in einzelne Stellen zerlegen ohne Stringkonvertieru
 
Zitat:

Zitat von Amateurprofi
@alzaimar:
In der letzten Zeile von NumberToDigits sollte es wohl besser heißen
Delphi-Quellcode:
SetLength (Result, n);

Ich dachte dabei an den Fall: aNumber = 0. Aber das ist sowieso nicht ganz korrekt. Es müsste eine Repeat-Until Schleife sein. Und dann hättest Du Recht.
Delphi-Quellcode:
Function NumberToDigits (aNumber : Cardinal) : TByteArray;
Var
  n : Integer;

Begin
  n := 0;
  SetLength (Result, 10);
  Repeat
    Result[n] := aNumber mod 10;
    aNumber := aNumber div 10;
    Inc (n);
  Until aNumber = 0;
  SetLength (Result, n1);
End;
..
// Beispiel
Var
  B : TByteArray;

Begin
  B := NumberToDigits (1234); // --> B = (4,3,2,1), also B[0] = 4, B[1] = 3 usw
  ...
@himitsu: Findst Du Assembler hier wirklich angebracht?

himitsu 26. Apr 2009 14:53

Re: Zahl in einzelne Stellen zerlegen ohne Stringkonvertieru
 
na OK, die paar Microsekunden machen es dann wohl auch nimmer aus :angel2:
aber im Grunde hätt ich das Ganze dann noch über 'nen statisches Array gemacht.

Zitat:

Ich dachte dabei an den Fall: aNumber = 0. Aber das ist sowieso nicht ganz korrekt.
dann hättest du bei aNumber = 0 auch nichts richtiges ... da dort zwar ein Wert im Array drinstünde,
bei aNumber > 0 immer ein Fehld mehr existieren würde
und der letzte Wert im Array undeffiniert wär :shock:


Na ok, im Prinzip machen unsere Functionen (deine Letzte und Meine) das Selbe (außer einer Divisions-Operation und noch ein paar Sachen bezüglich der Array-Verwaltung weniger)

ja und wie gesagt ... Types.TByteDynArray :zwinker:
Delphi-Quellcode:
Function NumberToDigits(aNumber: Cardinal): TByteDynArray;
Var n: Integer;
Begin
  n := 0;
  SetLength(Result, 10);
  Repeat
    Result[n] := aNumber mod 10;
    aNumber := aNumber div 10;
    Inc(n);
  Until aNumber = 0;
  SetLength(Result, n);
End;

EWeiss 26. Apr 2009 16:58

Re: Zahl in einzelne Stellen zerlegen ohne Stringkonvertieru
 
OT:

Alle Achtung es gibt Leute hier die haben Mathematisch echt was drauf.
:thumb:
Muss mal gesagt werden.

gruss Emil

richard_boderich 26. Apr 2009 18:15

Re: Zahl in einzelne Stellen zerlegen ohne Stringkonvertieru
 
Also der Algorithmus funktioniert nicht korrekt. Die letzte Stelle wird unterschlagen. :(
Habe jetzt den neuesten von himitsu getestet.

himitsu 26. Apr 2009 18:20

Re: Zahl in einzelne Stellen zerlegen ohne Stringkonvertieru
 
also bei mir laufen beide Varianten? :gruebel:

also das mir ASM
und der der letze Code (wobei der nur des Code von alzaimar #11 ist, nur ohne die Fehler bezüglich dem n1 und des TByteArray)

mirage228 26. Apr 2009 19:05

Re: Zahl in einzelne Stellen zerlegen ohne Stringkonvertieru
 
Ich würde sonst noch die Verwendung der Funktion Delphi-Referenz durchsuchenDivMod aus der Unit Delphi-Referenz durchsuchenMath vorschlagen. Sie verwendet zwar kein IDIV könnte aber ggf. schneller sein, als zwei gesonderte Aufrufe an DIV und MOD...

himitsu 26. Apr 2009 19:48

Re: Zahl in einzelne Stellen zerlegen ohne Stringkonvertieru
 
DivMod arbeitet nur mit Word und nicht mit Integer

mirage228 26. Apr 2009 19:54

Re: Zahl in einzelne Stellen zerlegen ohne Stringkonvertieru
 
Zitat:

Zitat von himitsu
DivMod arbeitet nur mit Word und nicht mit Integer

Hm, stimmt. Das also dazu :mrgreen:


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:00 Uhr.

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