:: MVP ::
|
|
:: RSS ::
|
|
|
Предисловие
Мне была поставлена задача сделать реестр для объектов из базы данных. При этом должна была быть возможность для групповой работы
с объектами. Я добавил колонку, в grid повесил на нее CheckBox, и для всех операций сделал проверку значения данного поля. Было
решено сделать PopupMenu с пунктами «Пометить все», «Снять все пометки», «Обратить пометки».
Врач вошел в палату для планового осмотра.
Он расспросил как самочувствие пациентов и уже готовился выйти.
Вдруг он разворачивается и спрашивает: «А зачем вы намотали провод от телевизора на ножку стула?»
Пациент побледнел, покраснел и сказал: «Было очень скучно…»
Делать три почти одинаковые процедуры или использовать if then else if было ниже звания программиста.
Начало
Есть логические операции, при выполнении которых результирующее значение равно первому операнду:
1 and 1 = 1
0 and 1 = 0
1 or 0 = 1
0 or 0 = 0
1 xor 0 = 1
0 xor 0 = 0
|
Поэтому (при условии, что a принадлежит [0,1]):
((a or 0) and 1) xor 0 = a
|
Рассуждения
Стоит изменить один из операндов, система выйдет из равновесия:
((a or 0) and 0) xor 0 = 0
((a or 0) and 1) xor 1 = !a
((a or 1) and 1) xor 0 = 1
|
Но если пойти дальше, то можно заметить, что второй операнд есть xor от первого и третьего:
((a or 0) and (0 xor 0)) xor 0 = 0
((a or 0) and (0 xor 1)) xor 1 = !a
((a or 1) and (1 xor 0)) xor 0 = 1
|
Или
c = ((a or b1) and (b1 xor b2)) xor b2
b1 = 0; b2 = 0; => c = 0
b1 = 0; b2 = 1; => c = !a
b1 = 1; b2 = 0; => c = 1
|
Если b1 и b2 представить как первый и второй бит байта, то можно записать:
b1 = (b shr 1) and 1; b2 = b and 1;
|
Тогда значение b можно хранить в атрибуте tag пункта меню:
b = 0 => c =0
b = 1 => c =!a
b = 2 => c =1
|
Результат
function TForm1.logmath(a, b: Integer): Integer;
var
b1, b2: Integer;
begin
b1 := (b shr 1) and 1;
b2 := b and 1;
Result := (((a or b1) and (b1 xor b2)) xor b2);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
// xor
Memo1.Lines.Add(IntToStr(0) + ' xor => ' + IntToStr(logmath(0, 1))); // 1
Memo1.Lines.Add(IntToStr(1) + ' xor => ' + IntToStr(logmath(1, 1))); // 0
// and 0
Memo1.Lines.Add(IntToStr(0) + ' set 0 => ' + IntToStr(logmath(0, 0))); // 0
Memo1.Lines.Add(IntToStr(1) + ' set 0 => ' + IntToStr(logmath(1, 0))); // 0
// or 1
Memo1.Lines.Add(IntToStr(0) + ' set 1 => ' + IntToStr(logmath(0, 2))); // 1
Memo1.Lines.Add(IntToStr(1) + ' set 1 => ' + IntToStr(logmath(1, 2))); // 1
end;
|
С практической точки зрения
procedure TForm1.Button2Click(Sender: TObject);
var
i: Integer;
function logmath(a: boolean; b: Integer): boolean;
var
b1, b2: Boolean;
begin
b1 := ((b shr 1) and 1) = 1;
b2 := (b and 1) = 1;
Result := (((a or b1) and (b1 xor b2)) xor b2);
end;
begin
// TButton(Sender).Tag: 2 - включить
// 0 - выключить
// 1 - переключить
for i := 0 to ComponentCount-1 do
if Components[i] is TCheckBox then
(Components[i] as TCheckBox).Checked :=
logmath((Components[i] as TCheckBox).Checked, TButton(Sender).Tag);
end;
|
Автор: Thunderchild.
.: Пример к данной заметке :.
|
При использовании материала - ссылка на сайт обязательна
|
|