Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Dezimal nach Dual umwandeln (https://www.delphipraxis.net/74375-dezimal-nach-dual-umwandeln.html)

Luckie 2. Aug 2006 01:57


Dezimal nach Dual umwandeln
 
OK, eigentlich trivial das Thema. Nehmen wir die Zahl 175 als Beispiel. Mit Papier und Bleistift würde man es so machen:
Code:
175
175 : 2 = 87 Rest 1
87 : 2 = 43 Rest 1
43 : 2 = 21 Rest 1
21 : 2 = 10 Rest 1
10 : 2 = 5 Rest 0
5 : 2 = 2 Rest 1
2 : 2 = 1 Rest 0
1 : 2 = 0 Rest 1
10101111
Dieser Algorithmus nach Delphi umgesetzt könnte so aussehen:
Delphi-Quellcode:
function dec2bin1(Value: Cardinal): String;
const
  s = '%d : %d = %d Rest %d';
var
  Rest: Cardinal;
  IntPart: Cardinal;
  Temp: Cardinal;
begin
  Temp := Value;
  IntPart := Value;
  while IntPart > 0 do
  begin
    Rest := IntPart mod 2; // Divisionsrest
    IntPart := Temp div 2; // ganzahlige Division
    writeln(Format(s, [Temp, 2, IntPart, rest]));
    Temp := IntPart;
    result := IntToStr(rest) + result;
    Sleep(175);
  end;
end;
(Das Writeln und das Sleep dienen nur zur Veranschaulichung.) Dies entspricht so ziemlich einer eins zu eins Umsetzung, wie man es auch im Kopf machen würden.

Jetzt kann man das Ganze aber noch, sagen wir mal, rein mathematisch machen:
Delphi-Quellcode:
function dec2bin2(Int: Integer): String;
var
  i : Integer;
begin
  Result := '';
  for i := 7 downto 0 do
  Result := Result + IntToStr((Int shr i) and 1);
end;
Doch da habe ich ein Verständnis Problem:
Warum läuft die Schleife von 7 runter auf 0?
Und was macht das ((Int shr i) and 1?
Was der Operator shr macht ist mir bekannt:
Aus 101 wird 010, wenn man das um eins nach rechts verschiebt. Aber warum macht man das und warum die logische Verknüpfung mit and 1?

Desweiteren: nehmen wir die Zahl 1234567890 als Beispiel. dec2bin1 liefert 1001001100101100000001011010010. dec2bin2 aber nur 11010010. Also die ersten acht Stellen bzw. so viele Stellen, wie die Schleife durchlaufen wird.

gmc616 2. Aug 2006 02:15

Re: Dezimal nach Dual umwandeln
 
Ohne jetzt die function dec2bin2 getestet zu haben, würde ich sagen:

Du testet den Integer vom Bit 7 bis Bit 0.
((int shr 7)AND 1) testet Bit7 auf 1 und ergibt ein Boolean.

Mit AND-Verkünpfungen kann man Integerwerte auf gesetzte Bits testen.
z.b:
Code:
5 AND 1 = 1

    0101  (=5)
AND 0001  (=1)
--------------
 =  0001  (=1)

 //oder
5 AND 4 = 4

    0101 (=5)
AND 0100 (=4)
--------------
 =  0100 (=4)

// oder
5 AND 2 = 0

     0101 (=5)
AND 0010 (=2)
---------
 =   0000 (=0)
in Dec2Bin2 testest du quasi das Bit 0 auf 1 oder 0.

Die Schleife läuft runter von 7 auf 0 um die Reihenfolge der Einsen und Nullen im Result-String beizubehalten.

Delphi-Quellcode:
for i := 0 to 7 do
  Result := IntToStr((Int shr i) and 1) + Result;
sollte genauso funktionieren.

Wenn du größere Zahlen als 65535 testen willst, muß du für die For-Schleife die Anzahl der zu testenden Bits ermitteln.

Martin K 2. Aug 2006 02:27

Re: Dezimal nach Dual umwandeln
 
Zunächst möchte ich mal meine Variante euch nicht vorenthalten, ist eine Vereinfachung des ersten Codes:
Delphi-Quellcode:
function DecToBin(Value: Cardinal): String;
begin
  repeat
    Result := IntToStr(Value mod 2) + Result;
    Value := Value div 2;
  until Value = 0;
end;
Zum zweiten Code:
Es liegt einfach daran, dass die Schleife von 7 auf 0 runterläuft und somit nur die rechten 8 Bits behandelt werden.
Man müsste also vorher die Anzahl der benötigten Bits berechnen (bei Cardinal maximal 32 :zwinker: ) und dann die Schleife z.B. von 31 auf 0 runter laufen lassen. Das funktioniert, getestet!
Die führenden Nullen dann zum Schluss noch zu entfernen sollte wohl nicht das Problem sein.

//Edit:
Die Anzahl der benötigten Bits zu berechnen ist ja eigentlich ganz einfach, so spart man sich auch das Entfernen der überflüssigen Nullen.
Die FOR-Schleife müsste also wie folgt abgeändert werden:
Delphi-Quellcode:
for i := Floor(Log2(Value)) downto 0 do

marabu 2. Aug 2006 06:33

Re: Dezimal nach Dual umwandeln
 
Guten Morgen.

Die Zahl der führenden Nullen kann man auch anders ermitteln. Und die Zahl der Speicheranforderungen durch schrittweises Vergrößern des Result-Strings lässt sich vermeiden:

Delphi-Quellcode:
function DualToStr(c: Cardinal): String;
const
  MAXLEN = 32;
var
  i: Integer;
begin
  SetLength(Result, MAXLEN);
  i := 0;
  repeat
    Inc(i);
    Result[MAXLEN - i] := Chr(Ord('0') + Ord(Odd(c)));
    c := c shr 1;
  until c = 0;
  Result := Copy(Result, MAXLEN - i, Succ(i));
end;
Grüße vom marabu

Amateurprofi 2. Aug 2006 11:09

Re: Dezimal nach Dual umwandeln
 
@Luckie
schau mal hier.
http://www.delphipraxis.net/internal...704&highlight=


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