本話題涉及: 1、常用二進位的位操作; 2、集合與 "位" 的關係; 3、TBits 類.
這裡的 "位" 是指二進位位, 譬如一個 Byte 有 8 個位、一個 Integer 有 32 個位.
在 C 語言中可以定義由 "位" 欄位構成的結構體, 但因效率問題好像使用也不廣泛.
假如要儲存八種狀態(True/False), 最笨的辦法可以使用下面的結構體:
type TState = record b1, b2, b3, b4, b5, b6, b7, b8: Boolean; end;
其實用 1 個位元組就可以表示 8 種狀態了, 因為 1 個位元組就有 8 個位.
這裡是假定用每個位表示一個狀態, 如果要算上各種組合這一個位元組能表示 255 種情形.
系統函數中的很多 "選項" 就是基於 "位".
先來幾個簡單的關於 "位" 的練習:
{這是查看二進位的函數}function ToBin(p: PByteArray; b: Integer): string;var i,j: Integer;begin Result := StringOfChar('0', b * 8); for i := 0 to b - 1 do for j := 0 to 7 do if Odd(p^[b-1-i] shr j) then Result[i*8 + 8 - j] := '1';end;{把一個位元賦給一個變數的方法}procedure TForm1.Button1Click(Sender: TObject);var b1,b2,b3: Byte;begin {雖 Delphi 常規下不支援二進位常量, 但其內嵌彙編支援} asm mov b1, 11100110B end; b2 := 230; b3 := $E6; {現在是給 b1 b2 b3 賦了同樣的值} ShowMessageFmt('%d, %d, %d', [b1, b2, b3]); //230, 230, 230end;{使用 or 確保第二、三位是 1}procedure TForm1.Button2Click(Sender: TObject);var b1, b2: Byte;begin asm mov b1, 11100010B mov b2, 00000110B end; b1 := b1 or b2; ShowMessage(ToBin(@b1, 1)); {11100110}end;{使用 and 確保第二、三之外的位是 0}procedure TForm1.Button3Click(Sender: TObject);var b1, b2: Byte;begin asm mov b1, 11100010B mov b2, 00000110B end; b1 := b1 and b2; ShowMessage(ToBin(@b1, 1)); {00000010}end;{使用 and 探測第二、三位是否是 1}procedure TForm1.Button4Click(Sender: TObject);var b: Byte;begin asm mov b, 11100010B end; if 2 and b = 2 then ShowMessage('第二位是 1'); {上面可以理解為: if 00000010B and b = 00000010B then ...} if 4 and b = 4 then ShowMessage('第三位是 1'); {上面可以理解為: if 00000100B and b = 00000100B then ...}end;{使用 shr 探測第二、三位是否是 1}procedure TForm1.Button5Click(Sender: TObject);var b: Byte;begin asm mov b, 11100010B end; if Odd(b shr 1) then ShowMessage('第二位是 1'); if Odd(b shr 2) then ShowMessage('第三位是 1');end;
用一個 Byte 值儲存八種狀態的執行個體:
準備工作:
1、在空白表單上添加 CheckListBox1;
2、添加四個 Button, 並啟用 Button1 的 OnClick 事件;
3、啟用表單的 OnCreate 事件.
var b: Byte; {用它記錄八個 CheckBox 的選擇狀態}procedure TForm1.FormCreate(Sender: TObject);begin CheckListBox1.Items.CommaText := 'A,B,C,D,E,F,G,H'; Button1.Caption := '儲存狀態'; Button2.Caption := '恢複狀態'; Button3.Caption := '全選'; Button4.Caption := '全不選'; Button1.Tag := 1; Button2.Tag := 2; Button3.Tag := 3; Button4.Tag := 4; Button2.OnClick := Button1.OnClick; Button3.OnClick := Button1.OnClick; Button4.OnClick := Button1.OnClick;end;procedure TForm1.Button1Click(Sender: TObject);var i: Integer;begin if TButton(Sender).Tag = 1 then b := 0; for i := 0 to CheckListBox1.Count - 1 do case TButton(Sender).Tag of 1: if CheckListBox1.Checked[i] then b := b or (1 shl i); 2: CheckListBox1.Checked[i] := Odd(b shr i); 3: CheckListBox1.Checked[i] := True; 4: CheckListBox1.Checked[i] := False; end;end;
測試("恢複" 寫成 "回複" 了):
"位" 操作有點抽象, 用 "集合" 代替上面的操作就簡明多了; 接下來討論 "集合" 的本質.