我有這個需要我需要存盤的地方:
- 最多 8
Boolean個值Byte - 最多 32 個
Boolean值(U)Int32 - 多達 64 個
Boolean值(U)Int64
比8位Byte更適合嗎?Char
我是否使用signed32/64unsigned位?
是否有特定于 Delphi 的代碼示例將Byte/轉換Integer為 / 從 s 陣列轉換Boolean?并將第 N 項設定為真/假,例如:
SetItemBoolean(ItemNumber: Integer; Value: Boolean);
我找到了一些可以從 a 轉換為 sChar陣列的東西Boolean,我只是想知道如何為Byte/做它,Integer這樣我就可以支持更多的Boolean值。
https://ibeblog.com/2010/08/20/delphi-binary-data-storage/
uj5u.com熱心網友回復:
Delphi 提供TIntegerSet了這個,它有一個 Integer 的大小,因此可以在它上面進行轉換。
var
Bits: TIntegerSet;
IntVal: Integer;
begin
if Value then
Include(Bits, ItemNumber)
else
Exclude(Bits, ItemNumber);
if ItemNumber in Bits then
{ Bit ItemNumber is set }
else
{ Bit ItemNumber is not set }
{ cast to Integer as needed }
IntVal := Integer(Bits);
{ or from Integer }
Bits := TIntegerSet(IntVal);
end;
對于一個位元組中的 8 位,您可以TByteSet以類似的方式宣告 a:
type
TByteSet = set of 0..7;
并將其轉換為 Byte 變數或從 Byte 變數轉換。
uj5u.com熱心網友回復:
這種型別實作了任意大小的位集。
type
TBitSet = record
private
FBitCount: Integer;
FSets: array of set of 0..255;
class function SetCount(BitCount: Integer): Integer; static;
procedure MakeUnique;
procedure GetSetIndexAndBitIndex(Bit: Integer; out SetIndex, BitIndex: Integer);
function GetIsEmpty: Boolean;
procedure SetBitCount(Value: Integer);
function GetSize: Integer;
public
class operator In(const Bit: Integer; const BitSet: TBitSet): Boolean;
class operator Equal(const bs1, bs2: TBitSet): Boolean;
class operator NotEqual(const bs1, bs2: TBitSet): Boolean;
class function SizeOfNativeSet(BitCount: Integer): Integer; static;
property BitCount: Integer read FBitCount write SetBitCount;
property Size: Integer read GetSize;
property IsEmpty: Boolean read GetIsEmpty;
procedure Clear;
procedure IncludeAll;
procedure Include(const Bit: Integer);
procedure Exclude(const Bit: Integer);
end;
{ TBitSet }
procedure TBitSet.MakeUnique;
begin
// this is used to implement copy-on-write so that the type behaves like a value
SetLength(FSets, Length(FSets));
end;
procedure TBitSet.GetSetIndexAndBitIndex(Bit: Integer; out SetIndex, BitIndex: Integer);
begin
Assert(InRange(Bit, 0, FBitCount-1));
SetIndex := Bit shr 8; // shr 8 = div 256
BitIndex := Bit and 255; // and 255 = mod 256
end;
function TBitSet.GetIsEmpty: Boolean;
var
i: Integer;
begin
for i := 0 to High(FSets) do begin
if FSets[i]<>[] then begin
Result := False;
Exit;
end;
end;
Result := True;
end;
procedure TBitSet.SetBitCount(Value: Integer);
var
Bit, SetIndex, BitIndex: Integer;
begin
if (Value<>FBitCount) or not Assigned(FSets) then begin
Assert(Value>=0);
FBitCount := Value;
SetLength(FSets, SetCount(Value));
if Value>0 then begin
(* Ensure that unused bits are cleared, necessary give the CompareMem call in Equal. This also
means that state does not persist when we decrease and then increase BitCount. For instance,
consider this code:
var
bs: TBitSet;
...
bs.BitCount := 2;
bs.Include(1);
bs.BitCount := 1;
bs.BitCount := 2;
Assert(not (1 in bs)); *)
GetSetIndexAndBitIndex(Value - 1, SetIndex, BitIndex);
for Bit := BitIndex 1 to 255 do begin
System.Exclude(FSets[SetIndex], Bit);
end;
end;
end;
end;
function TBitSet.GetSize: Integer;
begin
Result := Length(FSets)*SizeOf(FSets[0]);
end;
class function TBitSet.SetCount(BitCount: Integer): Integer;
begin
Result := (BitCount 255) shr 8; // shr 8 = div 256
end;
class function TBitSet.SizeOfNativeSet(BitCount: Integer): Integer;
begin
Result := (BitCount 7) shr 3; // shr 3 = div 8
end;
class operator TBitSet.In(const Bit: Integer; const BitSet: TBitSet): Boolean;
var
SetIndex, BitIndex: Integer;
begin
BitSet.GetSetIndexAndBitIndex(Bit, SetIndex, BitIndex);
Result := BitIndex in BitSet.FSets[SetIndex];
end;
class operator TBitSet.Equal(const bs1, bs2: TBitSet): Boolean;
begin
Result := (bs1.FBitCount=bs2.FBitCount)
and CompareMem(Pointer(bs1.FSets), Pointer(bs2.FSets), bs1.Size);
end;
class operator TBitSet.NotEqual(const bs1, bs2: TBitSet): Boolean;
begin
Result := not (bs1=bs2);
end;
procedure TBitSet.Clear;
var
i: Integer;
begin
MakeUnique;
for i := 0 to High(FSets) do begin
FSets[i] := [];
end;
end;
procedure TBitSet.IncludeAll;
var
i: Integer;
begin
for i := 0 to BitCount-1 do begin
Include(i);
end;
end;
procedure TBitSet.Include(const Bit: Integer);
var
SetIndex, BitIndex: Integer;
begin
MakeUnique;
GetSetIndexAndBitIndex(Bit, SetIndex, BitIndex);
System.Include(FSets[SetIndex], BitIndex);
end;
procedure TBitSet.Exclude(const Bit: Integer);
var
SetIndex, BitIndex: Integer;
begin
MakeUnique;
GetSetIndexAndBitIndex(Bit, SetIndex, BitIndex);
System.Exclude(FSets[SetIndex], BitIndex);
end;
uj5u.com熱心網友回復:
這是一個簡單的二進制邏輯。您可以以任何數字型別存盤資料,但我建議使用無符號型別。這是 BYTE 型別的示例,但您可以為任何(UInt16,UInt32,UInt64)撰寫相同的內容,只需更改 AStorage 引數的型別:
//for byte Index can be from 0 to 7
function GetByteBool(const AStorage : byte; AIndex : byte) : boolean;
begin
Result := (AStorage and (1 shl AIndex)) = (1 shl AIndex);
end;
procedure SetByteBool(var AStorage : byte; const AIndex : byte; const AValue : boolean);
begin
if AValue then begin
AStorage := AStorage or (1 shl AIndex);
end else begin
AStorage := AStorage xor (1 shl AIndex);
end;
end;
procedure TForm2.Button1Click(Sender: TObject);
begin
var b : byte := 17;
SetByteBool(b, 4, false);
if GetByteBool(b, 4) then
showmessage('true')
else
showmessage('false')
end;
在這種情況下,每 1 個布林值只使用 1 個 BIT。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/503934.html
