ド・モルガンの法則は大事!大事!超大事!

「ド・モルガンの法則」ってなにそれ?おいしいの?って聞かれたことがあります。
おいしくはないのですが、プログラムを書く上では超大事!です。

ここでは、プログラムを読み書きするうえでド・モルガンの法則をどのように使えばいいかを紹介します。

ド・モルガンの法則とは?

(知っている人は、次の章まで読み飛ばして構いません)

ド・モルガンの法則とは、以下の規則性のことです。

!(A || B) は (!A && !B) に等しい
!(A && B) は (!A || !B) に等しい

(ここで、|| は OR, && は AND, ! は NOT )

確認してみましょう。

!(A || B) は (!A && !B) に等しい
 +-------+-------+-------+
 |       | True  | False |
 +-------+-------+-------+
 | True  | False | False |
 | False | False | True  |
 +-------+-------+-------+
!(A && B) は (!A || !B) に等しい
 +-------+-------+-------+
 |       | True  | False |
 +-------+-------+-------+
 | True  | False | True  |
 | False | True  | True  |
 +-------+-------+-------+

簡単ですね。

プログラミングで役立つ場面

その1: if-else

例えば、以下の処理を考えてみます。

private void logic(boolean a, boolean b){
    if (a && b) {
        // 処理1
    } else {
        // 処理2
    }
}

ここで、処理1が実行される条件が何かというと「a が true、かつ b が true のとき」
では、処理2が実行される条件は?

elseif が成立しないときに実行されます。
つまり、 「NOT(if 条件)」のときです。
「(a が true、かつ b が true のとき)ではないとき」

よくわかりませんね。
そこで、ド・モルガンの法則を使います。

!(a && b)
→ !a || !b

つまり、「a が false、または b が false のとき」

これならわかりやすいですね。

その2: if - else if

続いて、次の処理を考えてみます。

private void logic(boolean a, boolean b){
    if (a && b) {
        // 処理1
    } else if (b) {
        // 処理2
    }
}

ここで、処理2が実行される条件は?

「b が true のとき」ではないです。
else if はそれまでの if 条件が成立しないときに実行されるからです。

つまり、「NOT(if条件)かつ(else if 条件)」のときに実行されます。
「(a が true、かつ b が true のとき)ではないとき、かつ b が true のとき」

よくわかりませんね。
そこで、再びド・モルガンの法則を使います。

!(a && b) && b
→ (!a || !b) && b

さらに論理を展開します。

(!a || !b) && b
→ (!a && b) || (!b && b)
→ (!a && b) || false
→ !a && b

つまり、「a が false かつ b が true のとき」

最初から、以下のように書いてくれていればわかりやすかったのですが…。1

private void logic(boolean a, boolean b){
    if (b) {
        if (a) {
           // 処理1
        } else {
            // 処理2
        }
    }
}

その3: while

ループを考えています。

boolean a = true;
boolean b = true;
while (a && b) {
    // 処理(この中で、a, b を変更)
}

このループの継続条件は、 while 式の通り「a が true、かつ b が true のとき」

では終了条件は?
継続条件が満たされないとき、つまり NOT(継続条件)です。

!(a && b)
→ !a || !b

つまり、終了条件は「a が false、または b が false のとき」
else のときと、考え方は同じですね。

 まとめ

ソースコードには、「else の実行条件」や「 while の終了条件」など、直接書かれていない条件が存在します。
特に、いいコードほどこうした論理的に導きだせることは書かれていません。冗長になるからです。

それらを明確に理解しながら読むには、論理演算の法則を適用して処理をひとつづつ読み解いていくことが大事です。

その中でも、ド・モルガンの法則は役に立つことが多い法則です。
覚えておいて損はないと思います。

--
え、ド・モルガンの法則なんて知らなくてもコードは読めるし書ける? そういう人は、天才です。たまにいます。


  1. 最初は if だけがあって、あとから仕様変更で else if を継ぎ足すという経緯があると、最初に提示したようなコードになりがちです。