![]() |
Warum ist bei dem negativen Integer das erste Bit 0?
Integer ist ein Variablentyp mit Vorzeichen (d.h. Plus/Minus). Das Vorzeichen wird meiner Kenntnis nach mit einem Bit gegenzeichnet, d. h. ist das erst Bit, von links gesehen, eine 0, dann ist die Zahl positiv. Ist es eine 1, ist die Zahl negativ. Für den Wert sind von den 32 Bit eines Integers nur 31 Bit nutzbar. Das 32'ste Bit ist für das Vorzeichen.
Das wollte ich mal überprüfen und habe den Code geschrieben. Allerdings ist das erste Bit immer eine 0, egal was für ein Wert ich nehme, positiv oder negativ. Wo liegt mein Fehler?
Delphi-Quellcode:
function BitAtPos(BitPos: Byte): Integer;
begin Result := 0; if (BitPos <= (SizeOf(Integer) * 8)) and (BitPos > 0) then Result := Integer(1) shl (BitPos - 1); end; //Liefert einen Binär-String aus 0 und 1 im Wert von Integer zurück. function IntToBinStr(Int: Integer): string; const b: array[Boolean] of Char = ('0', '1'); var i: Integer; begin Result := ''; for i := 1 to (SizeOf(Int) * 8) do Result := b[(Int and BitAtPos(i)) > 0] + Result; end; procedure TForm1.Button1Click(Sender: TObject); begin ShowMessage(IntToBinStr(-214748364)); end; |
AW: Warum ist bei dem negativen Integer das erste Bit 0?
So scheint es zu gehen:
Delphi-Quellcode:
function BitAtPos(BitPos: Byte): NativeUInt;
|
AW: Warum ist bei dem negativen Integer das erste Bit 0?
Oder auch so:
Delphi-Quellcode:
function IntToBinStr(Value: integer): string;
const BITS_PER_BYTE = 8; BIT_CHARS: array [Boolean] of char = ('0', '1'); var lLen: integer; i: integer; begin lLen := BITS_PER_BYTE * SizeOf(Value); SetLength(Result, lLen); for i := High(Result) downto Low(Result) do begin Result[i] := BIT_CHARS[Value and 1 = 1]; Value := Value shr 1; end; end; |
AW: Warum ist bei dem negativen Integer das erste Bit 0?
Dein BitAtPos liefert einen Integer zurück.
Delphi-Quellcode:
Alternativ wäre es mit einem Cardinal so auch korrekt funktional.
b[(Int and BitAtPos(i)) <> 0]
^^ Zitat:
![]()
Delphi-Quellcode:
function BitAtPos(BitPos: Byte): Integer;
begin Result := $1 shl BitPos; end; //Liefert einen Binär-String aus 0 und 1 im Wert von Integer zurück. function IntToBinStr(Int: Integer): string; const b: array[Boolean] of Char = ('0', '1'); var i: Integer; begin Result := ''; for i := 0 to SizeOf(Int) * 8 - 1 do Result := b[Int and ($1 shl i) <> 0] + Result; end;
Delphi-Quellcode:
function IntToBinStr(Int: Integer): string;
const b: array[Boolean] of Char = ('0', '1'); var i: Integer; begin Result := ''; for i := 0 to SizeOf(Int) * 8 - 1 do Result := b[Odd(Int shr i)] + Result; end;
Delphi-Quellcode:
function IntToBinStr(Int: Integer): string;
const b: array[Boolean] of Char = ('0', '1'); var i: Integer; begin SetLength(Result, SizeOf(Int) * 8); for i := 0 to SizeOf(Int) * 8 - 1 do Result[i + Low(string)] := b[Odd(Int shr i)]; end; Über Int als Bezeichner könnte man noch streiten, denn ![]() |
AW: Warum ist bei dem negativen Integer das erste Bit 0?
Zitat:
Integer und Cardinal sind beide 32-Bit und nehmen den gleichen MemorySpace ein. Nur dass Integer von außen als positiv oder negativ interpretiert wird und Cardinal als ausschließlich positiv, der eigentliche Speicherbereich ist aber nach wie vor gleich. Ich vermute, dass es an auch dieser Zeile liegt, wo das shl eben nicht das Integer richtig weiterschieben kann.
Delphi-Quellcode:
Ja, das ganze als Cardinal oder UInt32 sollte das lösen.
Result := Integer(1) shl (BitPos - 1);
Ich habe die Frage aber so verstanden, warum die Zeile oben eben bei Integer das Bit nicht richtig weiterschiebt, bei Cardinal aber doch. ![]() |
AW: Warum ist bei dem negativen Integer das erste Bit 0?
Vielen Dank, hat beim Integer (32) funktioniert. Der Tipp von Olli73 bezüglich Variablentyp-Änderung auf NativeUInt hat das Problem gelöst, zumindest beim Integer. Somit ist das Hauptproblem gelöst, mit dem ich zur Not leben kann.
Eigentlich wollte ich das für einige Variablentypen schreiben. Ein Schüler bat mich drum gebeten, für sein Informatik-Unterricht. Die Schüler wollen überprüfen ob die Bits, mit denen sie rechnen (Binärrechnen), tatsächlich so auch im Computer gespeichert werden. Die Version von DeddyH hat meine Version elegant verkleinert, und sie funktioniert bei Integer wunderbar. Jetzt versuche ich das Int64. Da habe ich noch meine Probleme. |
AW: Warum ist bei dem negativen Integer das erste Bit 0?
Ja, zum Integer passt aber eben nicht das > , da das größte Bit nunmal negativ ist (MinInt), weswegen ein <> eben richtiger wäre.
Aber da beim Cardinal alle Werte immer größer als 0 sind, passt dort auch das > , nur muß man eben vorher erstmal casten. PS: NativeUInt ist in Win32 ein Cardinal. :roll: Aber da es hier um 32 Bit geht, ist es z.B. für Win64 kompiliert aber komplett falsch. |
AW: Warum ist bei dem negativen Integer das erste Bit 0?
Ein alternativer Ansatz wäre:
Delphi-Quellcode:
mit
for i := 0 to (SizeOf(Int) * 8) - 1 do
Result := b[i in TIntegerSet(Int)] + Result;
Delphi-Quellcode:
aus System.SysUtils.TIntegerSet = set of 0..SizeOf(Integer) * 8 - 1; Das lässt such auch problemlos auf Int64 erweitern, wobei man dann
Delphi-Quellcode:
halt selbst deklarieren muss.TInt64Set = set of 0..SizeOf(Int64) * 8 - 1; |
AW: Warum ist bei dem negativen Integer das erste Bit 0?
PS: Wenn du den Code genau so 1:1 mit NativeUInt oder Cardinal kompilierst, wie in #2 erwähnt, also fröhlich Signed und Unsigned vermischst, dann könnte dir der Code spätestens in einem "neuen" Projekt ab Delphi 11 (oder 10) vielleicht wunderschön knallen, beim nun standardmäßig aktivem RangeCheck. :twisted: :lol:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:52 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-2025 by Thomas Breitkreuz