« Operacje logiczne, lekcja »
Rozdział 12. Operatory logiczne - sposób zapisywania koniunkcji, alternatywy i negacji w C++. (lekcja)
Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?
Zarejestruj się!
Autor: Piotr Szawdyński
Kurs C++

Operacje logiczne

[lekcja] Rozdział 12. Operatory logiczne - sposób zapisywania koniunkcji, alternatywy i negacji w C++.

Wprowadzenie

Zanim zaczniesz tworzyć jakieś pożyteczne programy, musisz przebrnąć przez masę podstaw. Na szczęście operacje logiczne są ostatnim podstawowym zagadnieniem, które należy wyjaśnić przed przejściem do właściwej nauki programowania w C++. Zanim podejmiesz się dalszej nauki C++, powinieneś mieć świadomość, że cała wiedza zebrana do tej pory będzie w 100% wykorzystywana w dalszych rozdziałach oraz będzie się nieustannie przeplatała wraz z nowymi, jeszcze nie omówionymi zagadnieniami. Jeśli więc czujesz, że jakiś rozdział był dla Ciebie nie do końca zrozumiały, to wróć teraz do niego.

Co to są operatory logiczne

Operatorami logicznymi nazywamy wszystkie spójniki klasycznego rachunku zdań. W przypadku języka C++ są to i, lub oraz negacja.

Podstawowe operatory logiczne

Jak już wcześniej napisałem w C++ istnieją trzy podstawowe operatory logiczne. Zapis formalny przedstawiam w poniższej tabeli:
NazwaJęzyk C++Opis
i&&Iloczyn logiczny - wszystkie wartości muszą być prawdziwe, aby została zwrócona prawda.
lub||Suma logiczna - co najmniej jedna z wartości musi być prawdziwa, aby została zwrócona prawda.
negacja!Zanegowanie wartości - czyli zwrócenie wartości przeciwnej.

Operator negacji

Zajmijmy się najpierw operatorem negacji. W klasycznym rachunku zdań istnieją tylko dwa stany: prawda i fałsz. Negacją prawdy jest fałsz, natomiast negacją fałszu jest prawda. Zobaczmy więc jak to możemy zapisać formalnie w C++:
C/C++
#include <iostream>
int main()
{
    bool wynik = true;
    std::cout << "wynik = " << wynik << std::endl;
    std::cout << "wynik = " <<!wynik << std::endl;
    std::cout << "wynik = " <<!!wynik << std::endl;
    wynik = !wynik;
    std::cout << "wynik = " << wynik << std::endl;
    wynik = !( 123 > 345 );
    std::cout << "wynik = " << wynik << std::endl;
    return 0;
}
Zobaczmy teraz wynik działania programu:
wynik = 1
wynik = 0
wynik = 1
wynik = 0
wynik = 1
Wyniki otrzymujemy takie, jakich można było się spodziewać po klasycznym rachunku zdań. Spójrzmy jednak jeszcze raz na kod źródłowy programu. Zauważ, że gdy używasz operatora negacji to nie są potrzebne zaokrąglone nawiasy, tak jak to było w przypadku operatorów porównania.

Operator sumy logicznej

Jeśli chcemy wykonać operację sumy logicznej, to tak jak w dodawaniu arytmetycznym będziemy potrzebowali co najmniej dwóch wartości - z tą różnicą, że tutaj będą to wartości logiczne. Najłatwiej będzie to zobrazować na przykładzie:
C/C++
#include <iostream>
int main()
{
    bool wynik = false || false;
    std::cout << "wynik (false || false) = " << wynik << std::endl;
    wynik = false || true;
    std::cout << "wynik (false || true) = " << wynik << std::endl;
    wynik = true || true;
    std::cout << "wynik (true || true) = " << wynik << std::endl;
    bool a = false;
    bool b = false;
    wynik = a || b || true;
    std::cout << "wynik (a || b || true) = " << wynik << std::endl;
    bool c = false;
    std::cout << "(a||b||c) = " <<( a || b || c ) << std::endl;
    b = true;
    std::cout << "(a||b||c) = " <<( a || b || c ) << std::endl;
    std::cout << "(a|| !b ||c) = " <<( a || !b || c ) << std::endl;
   
    return 0;
}
Zawartość konsoli po uruchomieniu programu:
wynik (false || false) = 0
wynik (false || true) = 1
wynik (true || true) = 1
wynik (a || b || true) = 1
(a||b||c) = 0
(a||b||c) = 1
(a|| !b ||c) = 0
Z wyników jakie otrzymaliśmy wynika, że suma logiczna faktycznie zwraca prawdę zawsze wtedy, gdy co najmniej jedna z wartości jest prawdziwa. Zwróć uwagę, że jeśli chcemy pisać wyrażenie bezpośrednio na ekran to musimy je 'opakować' w nawiasy z tego samego powodu, który został opisany w rozdziale poświęconym operatorom porównania.

Warto tutaj również wspomnieć, że klasyczny rachunek zdań w połączeniu z operatorami porównania daje bardzo duże możliwości manipulacji wynikami, jakie chcemy otrzymać. Oto przykład:
C/C++
#include <iostream>
int main()
{
    bool wynik;
    int liczba;
   
    liczba = - 100;
    wynik = liczba >= 10 || liczba < 0 || liczba == 7;
    std::cout << "liczba = " << liczba << ", wynik = " << wynik << std::endl;
   
    liczba = 0;
    wynik = liczba >= 10 || liczba < 0 || liczba == 7;
    std::cout << "liczba = " << liczba << ", wynik = " << wynik << std::endl;
   
    liczba = 7;
    wynik = liczba >= 10 || liczba < 0 || liczba == 7;
    std::cout << "liczba = " << liczba << ", wynik = " << wynik << std::endl;
   
    liczba = 8;
    wynik = liczba >= 10 || liczba < 0 || liczba == 7;
    std::cout << "liczba = " << liczba << ", wynik = " << wynik << std::endl;
   
    liczba = 10;
    wynik = liczba >= 10 || liczba < 0 || liczba == 7;
    std::cout << "liczba = " << liczba << ", wynik = " << wynik << std::endl;
   
    liczba = 100;
    wynik = liczba >= 10 || liczba < 0 || liczba == 7;
    std::cout << "liczba = " << liczba << ", wynik = " << wynik << std::endl;
    return 0;
}
Wynik działania powyższego programu będzie następujący:
liczba = -100, wynik = 1
liczba = 0, wynik = 0
liczba = 7, wynik = 1
liczba = 8, wynik = 0
liczba = 10, wynik = 1
liczba = 100, wynik = 1

Operator iloczynu logicznego

Iloczyn logiczny jest analogiczny w zapisie do sumy logicznej. Istotną różnicą są jednak otrzymywane wyniki. Prawdę otrzymamy wtedy i tylko wtedy gdy wszystkie wartości logiczne będą spełnione (czyli prawdziwe). Przejdźmy więc do kodu źródłowego kolejnego programu:
C/C++
#include <iostream>
int main()
{
    bool wynik = false && false;
    std::cout << "wynik (false && false) = " << wynik << std::endl;
    wynik = false && true;
    std::cout << "wynik (false && true) = " << wynik << std::endl;
    wynik = true && true;
    std::cout << "wynik (true && true) = " << wynik << std::endl;
    bool a = false;
    bool b = false;
    wynik = a && b && true;
    std::cout << "wynik (a && b && true) = " << wynik << std::endl;
    bool c = false;
    std::cout << "(a&&b&&c) = " <<( a && b && c ) << std::endl;
    b = true;
    std::cout << "(a&&b&&c) = " <<( a && b && c ) << std::endl;
    std::cout << "(a&& !b &&c) = " <<( a && !b && c ) << std::endl;
    std::cout << "(!a && b && !c) = " <<( !a && b &&!c ) << std::endl;
    return 0;
}
Tekst, który otrzymamy będzie następujący:
wynik (false && false) = 0
wynik (false && true) = 0
wynik (true && true) = 1
wynik (a && b && true) = 0
(a&&b&&c) = 0
(a&&b&&c) = 0
(a&& !b &&c) = 0
(!a && b && !c) = 1
Przeanalizuj otrzymane wyniki i sprawdź czy zgadzają się z zasadą przedstawioną w tym paragrafie.

Kolejność wykonywania operacji logicznych

Pamiętajmy, że tak samo jak w rachunku arytmetycznym, również tutaj obowiązuje kolejność wykonywania działań. Najważniejszy jest operator negacji, później wykonywane są operacje iloczynu logicznego, a na samym końcu sumy logicznej. Kolejnością wykonywania operacji można jednak manipulować poprzez zaokrąglone nawiasy - tak samo jak to miało miejsce w przypadku działań arytmetycznych. Zobaczmy na koniec program, który wykorzystuje całą omówioną w tym rozdziale wiedzę:
C/C++
#include <iostream>
int main()
{
    bool wynik;
   
    wynik = true && false || !true && false || !( !true && false );
    std::cout << "wynik = " << wynik << std::endl;
    return 0;
}

Zadanie domowe

Eksperymenty z programem

Poeksperymentuj z wartościami logicznymi ostatniego programu i sprawdź jak będą się zmieniały wyniki. Przeanalizuj swoje zmiany i sprawdź czy wiesz dlaczego otrzymujesz dane wyniki. Odpowiedz sobie na pytanie: czy mając dowolne wyrażenie logiczne zapisane na kartce, będziesz w stanie podać prawidłowo wartość końcową (wynik)?

Test kolejności operacji logicznych

Napisz odpowiedni program dzięki któremu przetestujesz kolejność wykonywania operacji logicznych. Zrób co najmniej dwa programy. Pierwszy z nich niech nie wykorzystuje nawiasów zaokrąglonych, drugi program natomiast niech będzie modyfikacją pierwszego, który wymusi inną kolejność wykonania działań niż jest to standardowo zapewnione przez język C++.
Poprzedni dokumentNastępny dokument
Operacje porównaniaInstrukcja warunkowa if ... else