FAQ VCL
Множества и перечисления

:: Меню ::
:: На главную ::
:: FAQ ::
:: Заметки ::
:: Практика ::
:: Win API ::
:: Проекты ::
:: Скачать ::
:: Секреты ::
:: Ссылки ::

:: Сервис ::
:: Написать ::

:: MVP ::

:: RSS ::

Яндекс.Метрика

Как определить количество элементов множества?

function GetElementCount(pSet: PByte; ByteSize: Integer): Integer;
const
  BitCnt: array[0..255] of Byte = (
    0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8);
var
  n: Integer;
begin
  Result := 0;

  while ByteSize >= 4 do
  begin
    if PLongInt(pSet)^ <> 0 then
      Inc(Result, BitCnt[pSet[0]] + BitCnt[pSet[1]] + BitCnt[pSet[2]] + BitCnt[pSet[3]]);
    Inc(PByte(pSet), 4);
    Dec(ByteSize, 4);
  end;

  if ByteSize >= 2 then
  begin
    Inc(Result, BitCnt[pSet[0]] + BitCnt[pSet[1]]);
    Inc(PByte(pSet), 2);
    Dec(ByteSize, 2);
  end;

  if ByteSize = 1 then
    Inc(Result, BitCnt[pSet[0]]);
end;

type
  TElement = (el1, el2, el3, el4);
  TElementSet = set of TElement;

procedure TForm1.Button1Click(Sender: TObject);
var
  aSet: TElementSet;
  aElementCount: Integer;
begin
  aSet := [el1, el4];
  aElementCount := GetElementCount(@aSet, SizeOf(aSet));
  ShowMessage(IntToStr(aElementCount));
end;


Как значение типа множество преобразовать в число?

function SetToInt(const aSet): UInt64;
var
  p: PByte;
  // PByte - для множества, включающего в себя не более 8 элементов.
  // Для множества из 16 элементов понадобится PWord и т.д.
  // С множеством из 256 элементов такой трюк не пройдет, т.к.
  // Delphi не поддерживает сверхбольшие числа (длинную арифметику).
begin
  p := Addr(aSet);
  Result := Integer(p^);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  fs: TFontStyles;
  Result: string;
begin
  fs := [fsItalic, fsStrikeOut];
  ShowMessage(SetToInt(fs).ToString);
end;

При использовании материала - ссылка на сайт обязательна