Autor |
Beitrag |
Passi077
      
Beiträge: 125
Win XP
D7 Pers
|
Verfasst: Sa 02.10.04 16:05
Hi,
ich möchte gerne eine Dezimalzahl in Hexadezimal umwandeln.
Dephi bringt da ja einige Funktionen mit um dies zu realisieren. Allerdings möchte ich, dass Delphi so arbeitet, wie man das als Mensch auch machen würde:
255:16=15 Rest 15 = FF
Leider kriege ich das nicht so richtig auf die Reihe. Wenn möglich mit den simpelsten Funktionen, die Delphi zu bieten hat. Hier mal mein bisheriger Code. Dabei wir im Label dann leider immer nur die letzte bzw. erste Hexadezimalziffer angezeigt (d.h. bis 15 funktioniert es..):
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: 53: 54:
| procedure TForm1.Button1Click(Sender: TObject); var x: extended; var y: integer; var z: integer; var w: integer; var t: integer; var i: integer; begin label3.Caption := ''; t:=scrollbar1.Position -8;
for i:=1 to 100 do begin
label4.Caption := inttostr(t);
x:=t / 16;
label1.Caption := floattostrf(x,fffixed,0,0);
y:= strtoint(label1.Caption); z:=y*16; w:=scrollbar1.Position - z;
if w < 10 then label3.Caption := inttostr(w) + label3.Caption else if w = 10 then label3.Caption := 'A' + label3.Caption else if w = 11 then label3.Caption := 'B' + label3.Caption else if w = 12 then label3.Caption := 'C' + label3.Caption else if w = 13 then label3.Caption := 'D' + label3.Caption else if w = 14 then label3.Caption := 'E' + label3.Caption else if w = 15 then label3.Caption := 'F' + label3.Caption;
if z < 16 then break else
t:=y;
end;
end; |
Sobald ich höher gehe bleibt es aber bei einer Ziffer.
Scrollbar1.position ist die Ausgangsdezimalzahl.
Außerdem kommt bei größeren Zahlen ein Fehler, da er diese dann anscheinend mit E rechnet und dies dann keiner Integer-Variable zugewiesen werden kann.
Wo ist der Fehler oder wie kann man das anders mit solch einfachen Mitteln noch realisieren?
Grüße,
Passi
Zuletzt bearbeitet von Passi077 am So 03.10.04 11:57, insgesamt 1-mal bearbeitet
|
|
.Chef
      
Beiträge: 1112
|
Verfasst: Sa 02.10.04 16:12
Gabs letztens erst, mit vollständiger Quelltextlösung: Hier!
Gruß,
Jörg
_________________ Die Antworten auf die 5 häufigsten Fragen:
1. Copy(), Pos(), Length() --- 2. DoubleBuffered:=True; --- 3. Application.ProcessMessages bzw. TThread --- 4. ShellExecute() --- 5. Keine Vergleiche von Real-Typen mit "="!
|
|
Passi077 
      
Beiträge: 125
Win XP
D7 Pers
|
Verfasst: Sa 02.10.04 16:35
Hmmm danke erst mal!
(Hab die Suche benutzt aber nach Hexadezimal gesucht...)
Aber irgendwie ist mir das zu kompliziert um ehrlich zu sein. Das muss für einen absoluten Anfänger sein *g* (keine Funktionen und sowas.. wieso-> haben wir in der Schule noch nicht, da sieht das so aus dem Internet rauskopiert aus).
In Visual Basic hab ich das quasi so hinbekommen wie mit dem oben geposteten Delphi Code. Aber in Delphi läuft das so leider nicht.
Ich verstehe eigentlich auch nicht wieso nicht.
Ich teile erst mal die Dezimalzahl durch 16 und mach auf etwas komplizierte Weise einen Integer draus (+8).
Dann nehme ich die enstandene Zahl mit 16 Mal und ziehe diese dann vom Ausgangwert ab, so dass ich den Rest hab. Den geb ich dann im Label aus.
Dann prüfe ich, ob der Faktor der beim Teilen rausgekommen ist größer als 16 ist und wenn ja setze ich den Ausgangwert zu diesem Faktor und fange von vorne an (desegen die Schleife). Aber wieso packt der das jetzt dann nicht einfach dazu?
Danke nochmal, aber muss einfach noch einfacher gehen, am besten eben so wie ich hier schon angefangen hab..
|
|
.Chef
      
Beiträge: 1112
|
Verfasst: Sa 02.10.04 16:47
So, wie du angefangen hast, ist milde ausgedrückt algorithmischer Unsinn. Ich vereinfache nochmal die Funktion von mir aus dem anderen Thread für Dezimal in Hexadezimal:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| function conv10to16(zahl : integer) : string; const ziffern : array[0..15] of Char = ('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'); var b : Integer; begin Result:=''; b:=Zahl; while b > 0 do begin Result:=ziffern[b mod 16]+Result; b:=b div 16; end; end; |
Kommst du damit klar? Wenn nicht, wo genau hängts? (Also bitte kein Kommentar a la "Versteh ich nicht.")
_________________ Die Antworten auf die 5 häufigsten Fragen:
1. Copy(), Pos(), Length() --- 2. DoubleBuffered:=True; --- 3. Application.ProcessMessages bzw. TThread --- 4. ShellExecute() --- 5. Keine Vergleiche von Real-Typen mit "="!
|
|
Passi077 
      
Beiträge: 125
Win XP
D7 Pers
|
Verfasst: Sa 02.10.04 17:02
Ok nochmal Danke!
Dann versuche ich jetzt den Code zu verstehn.
Delphi-Quelltext 1: 2:
| const ziffern : array[0..15] of Char = ('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'); |
Hier lege ich also für das result einfach für '0' '0' fest, für '5' '5', für '11' 'B' etc.? Das er eben das Result einfach von z.B. 1512 in FC umwandelt?
Delphi-Quelltext 1: 2: 3: 4: 5:
| while b > 0 do begin Result:=ziffern[b mod 16]+Result; b:=b div 16; end; |
Das verstehe ich nicht wirklich. Er macht das also mal solange bis b <= 0 ist, das is klar.
Aber was macht 'mod'? Und b:=b div 16 teilt also einfach b durch 16?
Also nochmals vielen Dank, wäre echt super wenn Du mir noch den letzten Abschnitt da erklären könntest.
Grüße
Passi
|
|
.Chef
      
Beiträge: 1112
|
Verfasst: Sa 02.10.04 17:04
Passi077 hat folgendes geschrieben: | Aber was macht 'mod'? |
Heißt ausgesprochen "modulo" und bildet den Rest einer Division, z.B. 12 mod 5 ergibt 2.
_________________ Die Antworten auf die 5 häufigsten Fragen:
1. Copy(), Pos(), Length() --- 2. DoubleBuffered:=True; --- 3. Application.ProcessMessages bzw. TThread --- 4. ShellExecute() --- 5. Keine Vergleiche von Real-Typen mit "="!
|
|
uall@ogc
      
Beiträge: 1826
Erhaltene Danke: 11
Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
|
Verfasst: Sa 02.10.04 17:35
@chef.
brauchst net noch extra ne variable b anlegen, kannst einfach mit zahl arbeiten
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| function conv10to16(zahl : integer) : string; const ziffern : array[0..15] of Char = ('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'); begin Result := ''; while zahl > 0 do begin Result := ziffern[zahl mod 16]+Result; zahl := zahl div 16; end; end; |
|
|
MartinPb
      
Beiträge: 698
|
Verfasst: Sa 02.10.04 18:01
Hier die Funktion anders ohne MOD
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| function conv10to16(zahl : integer) : string; const ziffern : array[0..15] of Char = ('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'); var b, c : Integer; s : String; begin Result := ''; b := Zahl;
while b > 0 do begin c := Trunc(((b / 16) - (b div 16)) * 16); b := b div 16;
s := ziffern[c]; Result:= s + Result; end; end; |
Hier wurde auf MOD (Modulo) verzichtet. Wie wird also jetzt c berechnet? Eigentlich genauso wie MOD, nur etwas ausführlicher. Zuerst wird b durch 16 geteilt. Wir haben eine Zahl mit einer Nachkommastelle. Uns interresiert nur die Nachkommastelle. Also ziehen wir von der Zahl den Vorkommawert ab. Das machen wir in dem wir wieder b durch 16 teilen, aber diesmal als Integerberechnung, d.h. ohne Nachkommastellen. Ziehen wir das eine avon dem anderen ab, dann bleibt nur noch der Nachkommawert. Dan multipizieren wir den Wert mit 16, weil wir eingentlich den Reswert der Berechnung haben wollen.
Aber was ist MOD? Beispiel:
Du hast 18 als Dezimalzahl. Den Hexwert kannst du wahrscheinlich auch im Kopf berechnen. In 18 past ein mal 16 und dann bleibt 2 übrich. Und Modulo berechnet dir diese 2.
Wenn du 18 durch 16 teilst, dann hast du 1,125 als Wert. Wir fragen anders: wenn du 18 durch 16 teilst und dich nur interresiert wie oft die 16 in 18 vorkommt, dann stellst du fest, daß es nur ein mal (oder 1). Aber was ist der Rest? Wenn 16 ein mal in 18 past, dann bleibt noch was übrig. Und das was übrig bleibt ist der Modulo Wert. Das kann man verschieden berechnen:
18 MOD 16 = 2
oder
18 / 16 = 1.125 => Rest 0.125 => 0.125 * 16 = 2
oder im Kopf
16 past ein mal in 18. Was übrig bleibt ist 2.
Aber das gleich mit anderen Zahlen:
7 past 3 mal in die 21 oder 21 / 7 = 3. Wir machen es aber schwerer: 20 MOD 7. Jetzt past es nicht mehr 3 sonder nur noch 2 mal. Übrig bleibt 6.
Nochmal:
98 MOD 10. Die 10 past 10 mal in die 100. In die 98 past die 10 nur 9 mal. Übrig bleibt 8. 98 MOD 10 = 8.
Noch fragen?
_________________ Gruß
Martin
|
|
.Chef
      
Beiträge: 1112
|
Verfasst: Sa 02.10.04 18:06
Ich vermute aber mal, dass meine Routine wesentlich schneller ist. Und übersichtlicher. 
_________________ Die Antworten auf die 5 häufigsten Fragen:
1. Copy(), Pos(), Length() --- 2. DoubleBuffered:=True; --- 3. Application.ProcessMessages bzw. TThread --- 4. ShellExecute() --- 5. Keine Vergleiche von Real-Typen mit "="!
|
|
Passi077 
      
Beiträge: 125
Win XP
D7 Pers
|
Verfasst: Sa 02.10.04 19:03
Ok Danke Leute, ich habe es jetzt Dank div und mod genau so hinbekommen wie ich es wollte:
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:
| procedure TForm1.Button1Click(Sender: TObject); var x: integer; var y: integer; var z: integer; begin label1.Caption :=''; z:=strtoint(edit1.Text);
while z > 15 do begin
y:=z div 16; x := z mod 16;
if x < 10 then label1.Caption := inttostr(x) + label1.Caption else if x = 10 then label1.Caption := 'A' + label1.Caption else if x = 11 then label1.Caption := 'B' + label1.Caption else if x = 12 then label1.Caption := 'C' + label1.Caption else if x = 13 then label1.Caption := 'D' + label1.Caption else if x = 14 then label1.Caption := 'E' + label1.Caption else if x = 15 then label1.Caption := 'F' + label1.Caption; label2.caption := inttostr(y);
z:=y;
if z < 16 then
if z < 10 then label1.Caption := inttostr(z) + label1.Caption else if z = 10 then label1.Caption := 'A' + label1.Caption else if z = 11 then label1.Caption := 'B' + label1.Caption else if z = 12 then label1.Caption := 'C' + label1.Caption else if z = 13 then label1.Caption := 'D' + label1.Caption else if z = 14 then label1.Caption := 'E' + label1.Caption else if z = 15 then label1.Caption := 'F' + label1.Caption;
;
end; end; |
Ich weiß selber dass das nicht die elegante Methode ist, aber das ist eindeutig die simpleste Methode wie man das machen kann würde ich behaupten.
Also vielen Dank für eure Hilfe!
Grüße
Passi
Zuletzt bearbeitet von Passi077 am Sa 02.10.04 19:16, insgesamt 1-mal bearbeitet
|
|
MartinPb
      
Beiträge: 698
|
Verfasst: Sa 02.10.04 19:16
Die simpelste nicht. Denn anscheinend blickst du nicht durch wie das mit
Delphi-Quelltext 1:
| ziffern : array[0..15] of Char = ('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'); |
funktioniert.
Du hast ein Array und dieses ist bereits mit Werten gefüllt. Den passenden Wert kannst du immer mit eine Zahl bekommen. Ist die Zahl 0, dann kriegst du 0. ISt sie 5, dann kriegst du 5. Ist sie 10, dann kriegst du A. Ist sie 15, dann kriegst du F.
Deinen ganzen Spuk mit
Delphi-Quelltext 1: 2:
| else if x = 10 then label1.Caption := 'A' + label1.Caption else if x = 11 then label1.Caption := 'B' + label1.Caption |
kannst du mit dem Array lösen.
Delphi-Quelltext 1:
| label1.Caption := ziffern[x] + label1.Caption |
Den Rest hast du noch doppelt gemacht. Ist die Zahl irgendwann kleiner 16, dann liefert MOD auch diese Zahl korrekt. 11 MOD 16 = 11, weil die 16 null mal in die 11 passt. Der Rest ist dann 11.
Du brauchst also kein extra Block für den wert unter 16.
_________________ Gruß
Martin
|
|
uall@ogc
      
Beiträge: 1826
Erhaltene Danke: 11
Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
|
Verfasst: Sa 02.10.04 21:11
Chef. meine ist schneller 
|
|
.Chef
      
Beiträge: 1112
|
Verfasst: Sa 02.10.04 21:21
_________________ Die Antworten auf die 5 häufigsten Fragen:
1. Copy(), Pos(), Length() --- 2. DoubleBuffered:=True; --- 3. Application.ProcessMessages bzw. TThread --- 4. ShellExecute() --- 5. Keine Vergleiche von Real-Typen mit "="!
|
|
Passi077 
      
Beiträge: 125
Win XP
D7 Pers
|
Verfasst: So 03.10.04 11:56
Jo ok das mit dem Array ist wirklich noch einfacher und die Abfrage unter 16 kann man tatsächlich weglassen.
Also nochmal vielen Dank an alle!
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: So 03.10.04 20:08
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Coder
      
Beiträge: 1383
Erhaltene Danke: 1
WinXP
D2005 PE
|
Verfasst: So 03.10.04 20:24
Hehe, und wieder ein neuling der den Fragenstatus nicht kennt. (logisch)
Ihr solltet echt mal einen Hinweis machen. 
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: So 03.10.04 20:49
Ist schon in Planung ... zumindest wollte sich TUFKAPL (AKA Christian S.) drum kümmern. 
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
|