- Обучающий курс. 10. Логические выражения в Delphi
- Логический тип данных
- Операции над логическими выражениями
- Немного об оптимизации
- Небольшое замечание
- Программирование or уроки and delphi
- DelphiComponent.ru — бесплатно видеоуроки по Delphi, статьи, исходники
- DelphiComponent.ru — бесплатно видеоуроки по Delphi, статьи, исходники
Обучающий курс. 10. Логические выражения в Delphi
Логические выражения — тема сравнительно небольшая, но очень важная. Логические выражения встречаются практически в каждой программе. Понять принцип их работы очень важно, чтобы при написании программ в Delphi не возникало трудностей с проверкой каких-либо данных.
Логический тип данных
С логическим типом данных мы уже неоднократно встречались при изучении свойств объектов. Этот тип данных состоит всего из двух значений: истина и ложь . На языке Pascal (а также на многих других языках) это соответственно True и False . В некоторых языках допускается использование чисел вместо этих переменных: 1 — истина, 0 — соответственно ложь. Итак, логический тип данных указывает, есть ли что-то или его нет, верно ли что-то или неверно.
В Pascal логический тип данных носит название Boolean (англ. — логический ). Значения, как уже было сказано — True и False . Простой пример объявления логической переменной и присвоения ей значения «ложь»:
Операции над логическими выражениями
А вот и самое интересное. Для логических выражений введены 4 операции. Работа с ними чем-то похожа на работу с числами. Рассмотрим подробно эти операции.
Как понятно из названия, данная операция меняет значение логического выражения на противоположное: если была истина, то станет ложь, а если была ложь, то станет истина. Выражение, над которым будет произведена операция, указывается либо после слова NOT через пробел, либо в скобках. Примеры:
m := not (k);
n := not m;
p := not ( not (m));
Подразумевается, что все переменные описаны типом данных Boolean . Итак, разберём, что здесь происходит:
- Сначала мы присваиваем переменной k значение True ;
- Далее, выполняя NOT для k получаем False: m становится равным False ;
- n становится противоположным m , т.е. True ;
- Над m делается двойное отрицание, т.е. значение p станет также False .
2. Логическое умножение (конъюнкция) — AND («и»)
В отличие от рассмотренного выше NOT , оператор AND работает уже с двумя (и более) выражениями. Логическое умножение равно истине тогда и только тогда, когда все выражения, связанные этим оператором, истинны. Если хотя бы один является ложью, то весь результат будет также ложью. Поэтому, собственно, операция и называется умножением: если истину обозначить за 1, а ложь — за 0, а числа перемножить, то при наличии хотя бы одного нуля весь результат будет нулевым. Примеры:
d := a and b;
e := a and c;
f := not (b) and c;
Значение d будет False , т.к. один из операндов ( операнды — выражения, которыми управляют операторы) равен False ( b ). Переменная e примет значение True , ведь и a и c истинны. Наконец, f тоже станет True , ведь not(b) — это истина и c тоже истина.
3. Логическое сложение (дизъюнкция) — OR («или»)
Как и AND , OR работает с несколькими операндами. Название «или» уже отвечает на вопрос «что будет в итоге»: если хотя бы один из операндов — истина, то всё выражение будет истиной. Результат False будет только в случае, если все операнды будут ложными.
Значение переменной c станет True , а переменной d — False .
Данная операция выдат результат True , если один из операндов является истиной, а другой — ложью, т.е. выражения не должны быть одинаковыми.
c := a xor b;
d := not (a) xor b;
e := not (a) xor not (b);
Переменная c станет истиной, ведь a и b различны, а d — ложью, т.к. под сравнение попадут два значения False . Наконец, e станет истиной.
Этих четырёх операций — NOT , AND , OR , XOR достаточно для построения логического выражения любой сложности. Эти операторы могут как угодно комбинироваться и можно составлять большие выражения. Однако следует заботиться и о скорости работы. Если выражение вычисляется один раз — всё в норме, но если оно будет вычисляться несколько тысяч раз (например, обработка информации из большой базы данных), то грамотность составленного выражения будет отражаться на скорости выполнения операции. Если в программе появились грмоздкие логические выражения, следует задуматься об их упрощении: одно условие всегда будет проверяться быстрее, чем два.
Немного об оптимизации
В Delphi есть специальные методы оптимизации, в том числе и для логических выражений. Дело в том, что в некоторых случаях вычисление логического выражения полностью не требуется, чтобы получить результат. Простые примеры на AND и OR :
A := False;
B := True;
C := True;
D := True;
Поскольку используется оператор AND , результат всего выражения будет истинным только в том случае, если все выражения будут истинны. В данном же случае уже первое выражение ( A ) ложно. Дальнейшая проверка просто не имеет смысла — всё равно результат останется False .
A := True;
B := False;
C := True;
D := False;
Абсолютно неважно, какие значения имеют B , C и D , ведь A истинно, а значит OR в любом случае выдаст True .
Изначально такая оптимизация в Delphi включена, т.е. выражения не будут вычисляться полностью. Эту возможность можно отключить (правда, непонятно — зачем?) в свойствах проекта: Project » Options » Compiler » Complete boolean eval (если включить эту опцию, то выражения будут вычисляться полностью).
Где применяются логические выражения? Практически повсюду. Они могут использовать лишь в программном коде для каких-либо проверок, а могут быть связаны и с интерфейсом программы. Как уже было сказано ранее, многие свойства компонент заданы логическим типом данных. Например, давайте сделаем две кнопки и запрограммируем их так, чтобы на экране всегда была только одна. Помещаем на форму 2 кнопки ( TButton ) и одну из них ( Button2 например) делаем невидимой: в Инспекторе Объектов изменяем свойство Visible на False . Теперь дважды щёлкаем по Button1 и пишем (дописать следует только то, что находится между begin и end):
procedure TForm1.Button1Click(Sender: TObject);
begin
Button1.Visible := False;
Button2.Visible := not Button1.Visible;
end ;
Разберёмся, что здесь происходит. Сначала мы изменяем видимость 1-ой кнопки — скрываем её. А затем меняем видимость 2-ой кнопки на противоложное первому. Аналогично пишем обработчик 2-ой кнопки:
procedure TForm1.Button2Click(Sender: TObject);
begin
Button2.Visible := False;
Button1.Visible := not Button2.Visible;
end ;
Если теперь запустить программу и пощёлкать по кнопкам, то они будут по очереди появляться на экране. В принципе, вторые строки обоих обработчиков можно написать и немного иначе — просто присвоить другой кнопке Visible:=True — результат не изменится. Такой способ приведён лишь в качестве примера использования оператора NOT.
Небольшое замечание
Следует обратить внимание ещё вот на что. Если в выражении несколько операндов, то их следует брать в скобки, расставляя таким образом приоритеты выполнения.
Программирование or уроки and delphi
Вроди бы все ясно как день, но вот с чем я столкнулся:
Сделал на форме(Delphi) панель (Height 186, Width 186). На панели кнопка (Height 186, Width 186, Left 0, Top 0, Tag 1).
. procedure TForm1.Button1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if Button = mbLeft then Button1.BeginDrag(false); end; procedure TForm1.Panel1DragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); begin Accept := Source is TButton end; procedure TForm1.Panel1DragDrop(Sender, Source: TObject; X, Y: Integer); begin case (source as TButton).Tag of 1: begin case ((source as TButton).Left) and ((source as TButton).Top) of ((0) and (0)): begin if ( X >= 93 ) and ( X < 186 ) and ( Y < 93 ) then begin (source as TButton).Left := 93; (source as TButton).Top := 0; end; if ( X < 93 ) and ( Y >= 93 ) and ( Y < 186 ) then begin (source as TButton).Left := 0; (source as TButton).Top := 93; end; end; end; // конец case left+Top блока end; // конец 1 tag end; // конец case tag блока end; // конец метода end.
Ну вот. Теперь кнопке можно присвоить новые координаты перетаскиванием. Ee можно перетащить вправо или вниз на панели. И как ни странно по диагонали. Т.е. сначала перетащить например на координаты Лефт и Топ = (0 и 93), а потом от туда перетащить на координаты (93 и 0), так же и обратно. К тому же, если начальные координаты кнопки будут например не (0 и 0), а (0, 3) ее так же можно будет перетаскивать. Почему, ведь стоит оператор AND:
. case ((source as TButton).Left) and ((source as TButton).Top) of ((0) and (0)): .
Теперь если подставить вместо AND оператор OR:
. case ((source as TButton).Left) or ((source as TButton).Top) of ((0) or (0)): .
то кнопку нельзя будет перетаскивать по диагонали. К тому же если начальные координаты кнопки будут отличны от (0, 0) то их вообще нельзя будет поменять перетаскиванием. Опять же странно. Такое ощущение что в операторе CASE: AND это OR, а OR это AND. Объясните пожалуста.
DelphiComponent.ru — бесплатно видеоуроки по Delphi, статьи, исходники
Если нужно выполнить два действия, то нужно написать так:
При проверке нескольких условий можно использовать несколько способов. Первый из них можно определить следующим образом:
Если условие1 верно, то выполнится следующее за логикой действие, а это вторая проверка. Если вторая проверка (условие 2) верна, то выполнится действие. Если хотя бы одно из условий не выполнится, то цепочка прерывается, и действие не будет выполнено.
Второй способ в большинстве случаев удобнее и нагляднее. Он может быть представлен следующим кодом:
В этом примере две проверки объединены в одну. Если Условие1 и Условие2 верны, то выполнится действие.
А если вам нужно выполнить действие, если хотя бы одно из условий верно? Не обязательно, чтобы оба сразу, а хотя бы одно. В этом случае можно для объединения использовать не and, a or. Это будет выглядеть так:
if (Условие1 выполнено) or (Условие2 выполнено) then Действие1;
Если вы объединяете два условия в один оператор if, то их обязательно нужно оградить скобками. Если вы их не поставите, то будет ошибка. Вот пример неправильного оформления:
В этом случае будет не объединение двух проверок, а бинарная операция (бинарные операции требуют отдельного разговора), для которой неправильно записана строка. Поэтому и возникает ошибка.
В качестве условий можно применять следующие операторы
DelphiComponent.ru — бесплатно видеоуроки по Delphi, статьи, исходники
Применяются к логическому типу данных, и результат также имеет логический тип. Операция логического отрицания унарная, остальные две — бинарные.
NOT- оператор логического отрицания НЕ:
Not False TRUE Not True FALSE
По этим примерам видно, что в результате выполнения этой операции истинное выражение становится ложным, и наоборот:
Var x, y: integer; X:= 7; Y:= 13; Not (7 > 13) TRUE Not (7 < 13) FALSE
AND - логическая операция И (конъюнкция).
Результат операции тогда и только тогда будет истинным, если истинны одновременно оба операнда:
OR- логическая операция ИЛИ (дизъюнкция).
Результат операции будет истинным, если хотя бы один операнд истинен:
XOR - логическая операция ИСКЛЮЧАЮЩЕЕ ИЛИ (исключающая дизъюнкция).
Результат операции тогда и только тогда будет истинным, если один операнд истинен, а второй ложен, во всех остальных случаях результат будет ложным:
В Delphiпо умолчанию логические выражения вычисляются по укороченному способу.
Это значит, что вычисления проводятся до тех пор, пока не станет заведомо известно значение всего выражения, после чего вычисления прекращаются. Например, рассмотрим выражение
Значение первого операнда равно FALSE, поэтому и результат вычисления всего операнда равен FALSE, даже если второй операнд истинен. Поэтому значение второго операнда вообще не вычисляется. Этот приём не только сокращает время вычислений, но и помогает избегать ошибок в программе:
If (n <> 0) and (m div n = 10) then m:= m +1;
В данном примере сначала проверяется, не равен ли делитель нулю. Если это так, то дальнейшие вычисления не производятся. Если же используется полное вычисление логического результата (включается директивой компилятора ), то при делении на ноль возникнет ошибка.