Autor |
Beitrag |
christoph
      
Beiträge: 28
Win XP(SPack1),Win 2000(Spack3)
Delphi 6(Spack2)
|
Verfasst: Mo 10.03.03 18:38
Hi allerseits wie kann man eiine Dezimal Zahl zerlegen?? Also ich habe Zahl(Typ Single) vom wert 0,0 bis 200,0. Ich möchte das jetzt jeder einzel wert (in einen Integerwert gewandelt wird...
Also bei der Zahl 199,1 sollte das dann so aussehen
Integer1 =1
Integer2 =9
Integer3 =9
Integer4 =1
Wir kann man das in Dlphi verwirklichen ??
Vielen Dank für eure Hilfe schon mal im Vorraus.
Gruss Christoph
|
|
derDoc
      
Beiträge: 623
Win Vista Prof
D2007 Prof
|
Verfasst: Mo 10.03.03 18:53
Ich würde umständlich erst deine Zahl in eine String verwandeln und dann den String in ein array of String zerschneiden. Zum Schluss jeden Teil des Arrays wieder in einen Integer umwandeln.
_________________ MfG derDoc
There are only 10 types of people: those who understand binary and those who don't.
|
|
Popov
      
Beiträge: 1655
Erhaltene Danke: 13
WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
|
Verfasst: Mo 10.03.03 20:29
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Di 11.03.03 15:40
@Popov: Deinen Quelltext verstehe ich nicht. Mit Trunc verlierst Du aber doch Stellen, oder?
So könnte man es machen:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| ziffern : ARRAY OF Integer;
implementation
{$R *.dfm}
procedure ziffern_suchen (zahl : Single); VAR my_zahl : Integer; begin while Trunc(zahl) <> zahl do zahl:=zahl*10; my_zahl :=Trunc(zahl);
SetLength(ziffern,0); repeat SetLength(ziffern,Length(ziffern)+1); ziffern[High(ziffern)]:=(my_zahl mod 10); my_zahl:=my_zahl div 10; until my_zahl = 0; end; |
Du musst das Array dann nur noch einmal umkrempeln, damit Du die richtige Reihenfolge hast.
MfG,
Peter
Moderiert von Klabautermann: Code- durch Delphi-Tags ersetzt
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
Udontknow
      
Beiträge: 2596
Win7
D2006 WIN32, .NET (C#)
|
Verfasst: Di 11.03.03 16:13
Hier mal meine Variante (ohne Umkrempeln...  ):
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| ziffern : ARRAY OF Integer;
procedure ziffern_suchen (zahl : Single); VAR str:String; var i:integer; begin Str:=FloatToStr(Zahl);
Str:=StringReplace(Str,',','');
SetLength(ziffern,Length(Str));
for i:=1 to Length(Str) do ziffern[i-1]:=StrToint(Str[i]); end; |
Cu,
Udontknow
Moderiert von Klabautermann: Code- durch Delphi-Tags ersetzt
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Di 11.03.03 16:35
Also, da das Array extrem klein bleiben wird, haben wir wohl kaum ein Speicher Problem. Die Geschwindigkeit habe ich mit diesem Quelltext getestet.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52:
| procedure ziffern_suchen (zahl : Single); VAR my_zahl,i : Integer; my_ziffern : Array of Integer; begin while Trunc(zahl) <> zahl do zahl:=zahl*10; my_zahl :=Trunc(zahl);
SetLength(my_ziffern,0); repeat SetLength(my_ziffern,Length(my_ziffern)+1); my_ziffern[High(my_ziffern)]:=(my_zahl mod 10); my_zahl:=my_zahl div 10; until my_zahl = 0;
SetLength(ziffern,Length(my_ziffern)); for i:=High(my_ziffern) TO 0 DO ziffern[High(ziffern)-i]:=my_ziffern[i]; end;
procedure ziffern_suchen_mit_str (zahl : Single); VAR str:String; var i:integer; begin Str:=FloatToStr(Zahl);
Str:=StringReplace(Str,',','',[]);
SetLength(ziffern,Length(Str));
for i:=1 to Length(Str) do ziffern[i-1]:=StrToint(Str[i]); end;
procedure TForm1.Button1Click(Sender: TObject); VAR zahl : Real; zeit1,zeit2,zeit,i : Integer; begin zahl:=2.147483647; zeit1:=GetTickCount; for i:=0 TO 999999 DO ziffern_suchen(zahl); zeit2:=GetTickCount; ShowMessage(IntToStr(zeit2-zeit1)); zeit1:=GetTickCount; for i:=0 TO 999999 DO ziffern_suchen_mit_str(zahl); zeit2:=GetTickCount; ShowMessage(IntToStr(zeit2-zeit1)); end; |
Und da ist meiner schneller! Ätsch!
Aber mal ehrlich: ich würde Deinen Algorithmus nehmen, denn die paar paar Millisekunden, die meiner schneller ist, tausche ich gerne gegen die Übersichtlichkeit Deines Algorithmus' ein!
MfG,
Peter
<edit>Du hast editiert! Das ist gemein! </edit>
Moderiert von Klabautermann: Code- durch Delphi-Tags ersetzt
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
Popov
      
Beiträge: 1655
Erhaltene Danke: 13
WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
|
Verfasst: Di 11.03.03 17:04
Peter Lustig hat folgendes geschrieben: | @Popov: Deinen Quelltext verstehe ich nicht. Mit Trunc verlierst Du aber doch Stellen, oder? |
Jo. Ich hab wieder mal falsch gelesen und verstanden, daß der Wert vorher in einen Integer gewandelt wird.
Dann sieht mein Code so aus:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| var i: Integer; s: String; begin s := FloatToStr(199.1); for i := 1 to Length(s) do if s[i] in ['0'..'9'] then ListBox1.Items.Add(s[i]); end; |
Da ich D3 habe kenne ich mich nicht mit dynamische Arrays kaum aus, deshalb ListBox1. Aber ich versuch es mal:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| var i: Integer; s: String; x: array of Integer; begin s := FloatToStr(199.1); for i := 1 to Length(s) do if not(s[i] in ['0'..'9']) then Delete(s, i, 1);
SetLength(x, Length(s)-1); for i := 1 to Length(s) do x[i-1] := StrToInt(s[i]); end; |
In x[0] ist der erste Wert.
Alternativ könnte man in x[0] die MaxLänge reinschreinen. Der Vorteil wäre, daß man weiß welche Werte echt sind. Das würde dann so aussehen:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| var i: Integer; s: String; x: array of Integer; begin s := FloatToStr(199.1); for i := 1 to Length(s) do if not(s[i] in ['0'..'9']) then Delete(s, i, 1);
SetLength(x, Length(s)+1); x[0] := Length(s);
for i := 1 to Length(s) do x[i] := StrToInt(s[i]); end; |
Jetzt ist in x[1] ist der erste Wert.
Moderiert von Klabautermann: Code- durch Delphi-Tags ersetzt
_________________ Popov
|
|
Udontknow
      
Beiträge: 2596
Win7
D2006 WIN32, .NET (C#)
|
Verfasst: Di 11.03.03 17:30
@Peter Lustig:
Menno!  Dafür funzt mein Algo auch mit Zahlentypen, die nicht zu Integer zuweisungskompatibel sind.  HCSTÄ!
Ich hatte mal irgendwo gelesen, daß, wenn man oft dynamischen Arrays neue Grössen gibt, es zu einer unnötigen Speicherreservierung kommt.
In diesem Falle reservierst du erst 4 Byte für einen Integerwert. Danach änderst du aber die Grösse auf 2 Integerwerte. Delphi muss nun fü den Array erneut vom Betriebssystem Speicher anfordern (und zwar für 8 Byte). Nun befindet sich der Array also an einem anderen Speicherbereich. Das ist aber noch lange kein Grund für Delphi, den vorigen Speicherbereich (der 4Byte groß war) an das Betriebssystem zurückzugeben. Stattdessen verweilt es in der Obhut eines Speicher-Managers, der im späteren Verlauf des Programmes diese 4 Byte für irgendetwas anderes zuteilen kann.
Delphi nimmt sich im Falle einer 5-Ziffer-Zahl also nicht 5*4 Byte an Speicher, sondern 1*4+2*4+3*4+4*4+5*4=(1+2+3+4+5)*4=60 Byte.
Für so kleine Dimensionen ist es natürlich irrelevant, ich habe aber schon Konstellationen gesehen, wo sich Programme über 300 MB Speicher zogen, nur weil die dynamische Größe von Arrays (oder auch TList-Instanzen, siehe Capacity) nicht einmal am Anfang, sondern immer wieder gestückelt erhöht wurde.
Das mit dem Speicher konnte ich nun leider nicht reproduzieren, aber die Leistung (Geschwindigkeit) einer Anwendung ist natürlich um einiges besser, wenn nur weniger Speicherzuweisungen erfolgen.
Cu,
Udontknow
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Di 11.03.03 17:52
@Udontknow:
Hm, ich sehe, dass das sehr schnell zu einem Problem werden kann. Ich habe eine Art Hybrid aus Deinem und meinem Algorithmus gemacht. Er ist jetzt schneller als mein Erster und müllt den Speicher nicht mehr zu:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| procedure ziffern_suchen_hybrid (zahl : Single); VAR my_zahl,i : Integer; my_ziffern : Array of Integer; begin while Trunc(zahl) <> zahl do zahl:=zahl*10; my_zahl :=Trunc(zahl);
SetLength(my_ziffern,Length(IntToStr(my_zahl))); repeat my_ziffern[High(my_ziffern)]:=(my_zahl mod 10); my_zahl:=my_zahl div 10; until my_zahl = 0;
SetLength(ziffern,Length(my_ziffern)); for i:=High(my_ziffern) TO 0 DO ziffern[High(ziffern)-i]:=my_ziffern[i]; end; |
Folgendes ist jetzt die Rangliste der Geschwindigkeit:
die Mischung von udontknow's und meinem
mein erster
popovs
udontknow's
MfG,
Peter
MfG,
Peter
Moderiert von Klabautermann: Code- durch Delphi-Tags ersetzt
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
Udontknow
      
Beiträge: 2596
Win7
D2006 WIN32, .NET (C#)
|
Verfasst: Di 11.03.03 18:28
Na gut, da muss ich wohl nachziehen:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26:
| procedure ziffern_suchen_mit_str2 (zahl : Single); VAR str:String; var i,j:integer; var Laenge:Integer; begin Str:=FloatToStr(Zahl);
Laenge:=Length(Str); if Pos(',',Str)>0 then Dec(Laenge);
SetLength(Ziffern,Laenge);
j:=0; for i:=1 to Laenge do begin if Str[i]=',' then Continue; Ziffern[j]:=Ord((Str[i]))-48; Inc(j); end; end; |
BTW: Interessant ist, daß die zweite Prozedur langsamer ist, als wenn sie alleine läuft...
Cu,
Udontknow
Moderiert von Klabautermann: Code- durch Delphi-Tags ersetzt
|
|
christoph 
      
Beiträge: 28
Win XP(SPack1),Win 2000(Spack3)
Delphi 6(Spack2)
|
Verfasst: Di 11.03.03 22:49
Himmel da hab ich aber ne Flut von Antworten bekommen..
Also erstmal ein riesen Dank für die Ganzen Antworten Hammer!!!!!
Hier nun mal mein Code.....
Wie gesagt zur erinnerung ich wollte ja jeweils dei einzelen Zahlen haben
nur ob das jetzt länger oder schneller geht wie euer Code müsste man testen....
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| procedure TForm1.Button1Click(Sender: TObject); var i1,i2,i3,i4,i5:word; i :Integer; Zahl :single; begin Zahl :=(strtofloat(Nummer.Text)*10); i :=trunc(zahl); divmod(i,10000,i1,i2); Nr1.Value := i2; divmod(i,1000,i2,i3); Nr2.Value := i3; divmod(i,100,i3,i4); Nr3.Value := i4; divmod(i,10,i4,i5); Nr4.Value := i5; end; |
Grüsse Chris
Moderiert von Klabautermann: Code- durch Delphi-Tags ersetzt
Zuletzt bearbeitet von christoph am Fr 14.03.03 01:36, insgesamt 3-mal bearbeitet
|
|
derDoc
      
Beiträge: 623
Win Vista Prof
D2007 Prof
|
Verfasst: Do 13.03.03 10:10
Ich glaube die Geschwindigkeitsunterschiede sind im geringen Bereich, dein Code sollte da aber ganz gut abschneiden. Wenn er läuft kannst du ihn doch benutzen. Die Millisekunden machen die Sau nicht fett.
_________________ MfG derDoc
There are only 10 types of people: those who understand binary and those who don't.
|
|
|