Autor Beitrag
catweasel
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 487
Erhaltene Danke: 1

Win 7 64bit
Delphi 7 Second Sedition V7.2
BeitragVerfasst: Mo 09.02.04 20:36 
Hi,

ich steh gerade ein bischen auf dem Schlauch. Hab mich mit Bitmanipulation noch nicht so bechäftigt..
Meine Frage ist: Wie kann ich die Bits eines Bytes auslesen...

Ich möchte im Prinzip etwas haben wie:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
var
bitarray : array[1..8of boolean;
x : byte;

function getbits(x:byte): array of boolean:
var z : integer;
begin
for z:= low(bitarray) to high(bitarray) do
  Result[z] := 
// Naja hier müsste ich irgendwie an die Bits des übergebenen X
// rankommen ....
end;


Ich denke was das werden soll ist klar:
Je nachdem ob das Bit eine 1 oder 0 ist soll das array true oder false enthalten.... Wie mache ich das .. ?

Catweasel

_________________
Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Mo 09.02.04 21:07 
Ungetestet, aber müsste funktionieren...
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
type
  TBitArray = array[0..7of Boolean;

function getbits(x: Byte): TBitArray:
var
  i: Integer;
begin
  for i := Low(Result) to High(Result) do
    Result[i] := Boolean(x and (1 shl i));
end;

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
catweasel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 487
Erhaltene Danke: 1

Win 7 64bit
Delphi 7 Second Sedition V7.2
BeitragVerfasst: Mo 09.02.04 21:13 
Zitat:
Boolean(x and (1 shl i));


hm... ich kann irgendwie mit der Funtion boolean() nix anfangen.. Gibts die überhaupt (ich kann die nirgends finden ...) ?

Catweasel...

_________________
Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.
obbschtkuche
Gast
Erhaltene Danke: 1



BeitragVerfasst: Mo 09.02.04 21:23 
Das ist keine Fkt, sondern ein Typecast von irgendeinem integer nach boolean
catweasel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 487
Erhaltene Danke: 1

Win 7 64bit
Delphi 7 Second Sedition V7.2
BeitragVerfasst: Mo 09.02.04 21:32 
öhmmm :oops: achso ... :)

_________________
Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Mo 09.02.04 21:36 
obbschtkuche hat folgendes geschrieben:
Das ist keine Fkt, sondern ein Typecast von irgendeinem integer nach boolean

Ganz genau..!

ausblenden Delphi-Quelltext
1:
1 shl i					

die Zahl Eins wird um i Stellen nach links geshiftet

ausblenden Delphi-Quelltext
1:
and (1 shl i)					

x wird mit dem Ergebnis der Shift-Operation and-verknüpft. Ist das Bit gesetzt, dann ist das Ergebnis ein Vielfaches von 2, andernfalls 0

ausblenden Delphi-Quelltext
1:
Boolean(x and (1 shl i))					

Dieser Typecast wandelt das Ergebnis in einen Boolean (True/False) um. Dabei gilt 0=False und als umkehrschluss - alles was ungleich null ist ist dann True..!

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
catweasel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 487
Erhaltene Danke: 1

Win 7 64bit
Delphi 7 Second Sedition V7.2
BeitragVerfasst: Mo 09.02.04 23:34 
Ah Danke ..!

_________________
Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.
catweasel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 487
Erhaltene Danke: 1

Win 7 64bit
Delphi 7 Second Sedition V7.2
BeitragVerfasst: Di 10.02.04 00:34 
Zitat:
Boolean(x and (1 shl i))


Das das da oben ein Cast ist hab ich nu kapiert... :)

Aber eine Frage noch... : :?:

ich hab noch ein bischen an den Operatoren shl bzw. shr zu kabbern und muss mir das mit den logischen Operatoren nochmal genauer anguggen..
Z.B. Warum gerade die Zahl 1 verschieben.. :?:

@motzi (oder sonst jemand :-) )

Könntest du mir zu lernzwecken auch die Umkehrfunktion kurz erläutern?
Also

ausblenden Delphi-Quelltext
1:
function getbyte(bitarray:TBitarray):byte;					


Wäre super.. :-)

Catweasel

_________________
Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.
Sven
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 314


D6 Ent, K3 Pro (patched)
BeitragVerfasst: Di 10.02.04 08:10 
Nur mal am Rande, in der Unit Classes ist ein Typ deklariert der da heißt TBits. Vielleicht leistet dieser bessere Dienste.

_________________
MDK 9.1, Kernel 2.4.21, KDE 3.1 Kylix 3 Pro (patched), nutze aber auch Windows
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Di 10.02.04 14:29 
Also shl / shr sind im Prinzip ganz einfach.. sie verschieben die Bits einfach um x Bit nach rechts oder links und füllen die dabei entstehenden Leerräume einfach mit Nullen.
ausblenden Quelltext
1:
2:
3:
00000001 shl 1
--------------
00000010


ausblenden Quelltext
1:
2:
3:
00000001 shl 5
--------------
00100000


Ich verschiebe in dem Code die Zahl 1 weil sie in der Binär-Darstellung nur eine 1 hat und die an erster Stelle ist. Ich shifte dann einfach immer um i Stellen wodurch ich dann immer das nächste Bit gesetzt habe:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
00000001 shl 0 = 00000001
00000001 shl 1 = 00000010
00000001 shl 2 = 00000100
00000001 shl 3 = 00001000
00000001 shl 4 = 00010000
00000001 shl 5 = 00100000
00000001 shl 6 = 01000000
00000001 shl 7 = 10000000

Das wird dann per and verknüpft und das Ergebnis in einen Boolean umgewandelt.

Die Umkerfunktion könnte also ungefähr so ausschauen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
function GetByte(const aBitArray: TBitArray): Byte;
var
  i: Integer;
begin
  Result := 0;
  for i := Low(aBitArray) to High(aBitArray) do
    if aBitArray[i] then
      Result := Result or (1 shl i);
end;

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
AndyB
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1173
Erhaltene Danke: 14


RAD Studio XE2
BeitragVerfasst: Di 10.02.04 15:55 
Motzi hat folgendes geschrieben:
ausblenden Delphi-Quelltext
1:
Boolean(x and (1 shl i))					

Dieser Typecast wandelt das Ergebnis in einen Boolean (True/False) um. Dabei gilt 0=False und als umkehrschluss - alles was ungleich null ist ist dann True..!

Gut beobachtet. Und wenn jetzt jemand kommt, und mit
if BitArray[x] = True then testet, wird er bis auf BitArray[0] immer False bekommen, weil True für Boolean als True = 1 deklariert ist. Da ab (einschließlich) Byte(BitArray[1]) > 1 ist, ergibt eben "x = 1 mit x>1" immer False.

Aus diesem Grund beforzuge ich erstens
ausblenden Delphi-Quelltext
1:
if BitArray[x] then					

und zeitens unterlasse ich Typecasts zu Boolean, wenn das nicht unbedingt nötig ist, indem ich auf ungleich Null prüfe.
ausblenden Delphi-Quelltext
1:
Result[i] := x and (1 shl i) <> 0;					

Dadurch übernimmt der Compiler die nötige Umwandlung und macht aus allen Werten ungliech 0 die 1.

_________________
Ist Zeit wirklich Geld?
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Di 10.02.04 18:41 
AndyB hat folgendes geschrieben:
Aus diesem Grund beforzuge ich erstens
ausblenden Delphi-Quelltext
1:
if BitArray[x] then					

Tu ich auch (wie man oben sieht)...

Zitat:
und zeitens unterlasse ich Typecasts zu Boolean, wenn das nicht unbedingt nötig ist, indem ich auf ungleich Null prüfe.
ausblenden Delphi-Quelltext
1:
Result[i] := x and (1 shl i) <> 0;					

Dadurch übernimmt der Compiler die nötige Umwandlung und macht aus allen Werten ungliech 0 die 1.

Stimmt.. das hab ich nicht beachtet.. dachte bis jetzt es wird jeder Wert <> 0 als True angesehen, dies trifft aber nur bei einer Prüfung ala
ausblenden Delphi-Quelltext
1:
if Ausdruck then					

zu und nicht bei
ausblenden Delphi-Quelltext
1:
if Ausdruck = True then					

da ja ein Boolean im Prinzip eine Menge mit 2 Werten darstellt und Ord(True) = 1 ist...

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
catweasel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 487
Erhaltene Danke: 1

Win 7 64bit
Delphi 7 Second Sedition V7.2
BeitragVerfasst: Di 10.02.04 23:30 
Zitat:
Nur mal am Rande, in der Unit Classes ist ein Typ deklariert der da heißt TBits. Vielleicht leistet dieser bessere Dienste.

Naja soo aufregend is der TBits typ ja auch nich... Is ja auch nur ein array of boolean.. gut ok.. es dimensioniert sich selbst.. aber wann hat ein byte schonmal weniger oder mehr als 8 bits ...?
Ich geb zu: für words und doubblewords isses ganz brauchbar, aber für byte reicht auch das eigene Array....
Oder kann TBits noch was geniales das ich übersehen hab ?

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
function GetByte(const aBitArray: TBitArray): Byte; 
var 
  i: Integer; 
begin 
  Result := 0
  for i := Low(aBitArray) to High(aBitArray) do 
    if aBitArray[i] then 
      Result := Result or (1 shl i); 
end;


Da muss ich da auch analog zur getbits funktion auf <> 0 testen, oder?!

Zitat:
Gut beobachtet. Und wenn jetzt jemand kommt, und mit
if BitArray[x] = True then
testet,


Genau das hab ich nämlich beobachtet .. Bit 1 war immer abwechseln false oder true und der rest immr false...

Zitat:
Dadurch übernimmt der Compiler die nötige Umwandlung und macht aus allen Werten ungliech 0 die 1

Genau da liegt irgendwie das Problem. Man denkt ein bool wert is true wenn er wahr is und dann ist er auf einmal war wenn er falsch wahr ist .. :shock: Ist das jetzt doppelte Verneinung oder was ? :roll:

Wo liegt genau der Unterschied zwischen:

if Ausdruck then und  if Ausdruck = True then

Und vor allem: Was macht der Compiler da einfach so.. Und warum geht der type cast in diesem Fall schief ?

Catweasel

_________________
Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.
AndyB
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1173
Erhaltene Danke: 14


RAD Studio XE2
BeitragVerfasst: Mi 11.02.04 10:03 
catweasel hat folgendes geschrieben:
Da muss ich da auch analog zur getbits funktion auf <> 0 testen, oder?!

Nein, denn hier interessiert dich ja, welches Bit gesetzt ist.


Zitat:
Und warum geht der type cast in diesem Fall schief ?

Der Typecast geht hier nicht schief, aber er liefert ein Ergebnis, das man nicht gleich ("=") einem Wert setzen darf.
Ein Beispiel:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
True = 0000 0001
False = 0000 0000

Result := Boolean(1 shl 3)    = 0000 1000
if Result = True then      =  if 0000 1000 = 0000 0001 then  FEHLER

// für das Erste Bit kommt hier fogendes heraus:
Result := Boolean(1 shl 0)    = 0000 0001
if Result = True then      =  if 0000 0001 = 0000 0001 then   OK

// Mit <> 0 testen:
Result := 1 shl 3 <> 0    = 0000 0001
if Result = True then      =  if 0000 0001 = 0000 0001 then   OK


Zitat:
Was macht der Compiler da einfach so.

Er macht aus
ausblenden Delphi-Quelltext
1:
Result := 1 shl 3 <> 0;					

grob diesen Code:
ausblenden Delphi-Quelltext
1:
if 1 shl 3 <> 0 then Result := True else Result := False;					

Da der Compiler Assembler-Code produziert, kann er das noch ganz schön optimieren, womit es nicht spührbar langsamer als der direkte Typecast läuft.

Zitat:
Wo liegt genau der Unterschied zwischen:
if Ausdruck then und  if Ausdruck = True

Bei erstem prüft der Compiler auf "<> 0". Bei zweiten wird direkt mit "= 1" geprüft.

_________________
Ist Zeit wirklich Geld?