Logika matematyczna to jedna z bardziej przydatnych w programowaniu (i ogólnie informatyce) dziedzin matematyki. Dzięki prawom logiki działają wszystkie układy elektroniczne. W codzienności programisty może przydać się zwłaszcza podczas optymalizacji warunków logicznych.
Przykładowo, inspekcja kodu Ruby w środowisko IntelliJ za błąd uważa sterowanie przepływem za pomocą negatywnego warunku typu: if !condition ...
. Taki pojedynczy warunek wystarczy w takim przypadku zamienić na: unless condition ...
. W przypadku bardziej rozbudowanych warunków przydają się znane z liceum prawa de Morgana.
I prawo de Morgana (zaprzeczenia koniunkcji)
~(p ^ q) <==> (~p v ~q)
Poniższy kod sprawdza, czy jest widoczny nagłówek. Nagłówek powinien mieć tytuł oraz podtytuł. Jeżeli obydwa tytuły są widoczne, uznajemy ze jest wyświetlony poprawnie. I tak następujące instrukcje warunkowe:
if !is_title_displayed || !is_subtitle_displayed puts 'Header not visible!' end
można zamienić na:
unless (is_title_displayed && is_subtitle_displayed) puts 'Header not visible!' end
Zobaczmy, jak to działa.
def check(p, q) if !p || !q puts 'Header not visible!' else puts 'Header is displayed.' end end def check_morgan(p, q) unless p && q puts 'Header not visible!' else puts 'Header is displayed.' end end
Test, czy obydwie funkcje są sobie równoważne:
is_title_displayed=true is_subtitle_displayed=true check(is_title_displayed,is_subtitle_displayed) => Header is displayed. check_morgan(is_title_displayed,is_subtitle_displayed) => Header is displayed. is_title_displayed=true is_subtitle_displayed=false check(is_title_displayed,is_subtitle_displayed) => Header not visible! check_morgan(is_title_displayed,is_subtitle_displayed) => Header not visible! is_title_displayed=false is_subtitle_displayed=true check(is_title_displayed,is_subtitle_displayed) => Header not visible! check_morgan(is_title_displayed,is_subtitle_displayed) => Header not visible! is_title_displayed=false is_subtitle_displayed=false check(is_title_displayed,is_subtitle_displayed) => Header not visible! check_morgan(is_title_displayed,is_subtitle_displayed) => Header not visible!
Obydwie metody zachowują się identycznie.
II prawo de Morgana (zaprzeczenia alternatywy)
~(p v q) <==> (~p ^ ~q)
Poniższy kod zwraca wartość true
, gdy linia zawiera jakieś znaki i nie zawiera napisu "Serial number"
.
def validate(line) if !line.empty? && !line.include?('Serial Number') puts 'True' else puts 'False' end end def validate_morgan(line) unless(line.empty? || line.include?('Serial Number')) puts 'True' else puts 'False' end end
Oczywiście funkcje te można zapisać w krótszej formie, ale dla celu artykułu pozostawiam formę rozwiniętą, gdzie lepiej widać, do się dzieje.
Czas na sprawdzenie poprawności…
Prawidłowa linia:
line='QWERTY' validate(line) => True validate_morgan(line) => True
Nieprawidłowe linie:
line='' validate(line) => False validate_morgan(line) => False line='Serial Number' validate(line) => False validate_morgan(line) => False
Funkcje są sobie równoważne.
Zasady logiki to jednak nie tylko prawa de Morgana. Warto przypomnieć sobie np. tablice tautologii.