ド・モルガンの法則とは、論理と真理値表で否定を書き直す

回 1-4 道 1 数と論理と計算量

ド・モルガンの法則は、「A かつ B、ではない」は「A でないか、B でないか」と同じで、「A または B、ではない」は「A でもなく、B でもない」と同じ、という決まりです。否定をかっこの中へ配るときは、AND と OR を入れ替えます。2 つの条件なら組み合わせは 4 通りしかないので、真理値表で全部の行を比べれば、いつでも同じだと確かめられます。

否定の入った条件式を、AND と OR を入れ替えて書き直し、意味が変わっていないかを真理値表の全部の行で確かめられるようになります。

「ログインしていて権限がある、ではない」を書き直せますか

「A かつ B、ではない」は、「A でないか、B でないか、のどちらか」と同じです。これがド・モルガンの法則です。

会員だけが見られる頁で、次の条件を考えます。「ログインしていて、かつ権限がある、のでなければ断る」。コードにすると not (logged_in and has_perm) です。

この条件を、断る理由ごとに分けて書きたくなることがあります。「ログインしていない」なら断る。「権限が無い」なら断る。どちらか 1 つでも当てはまれば断るので、「または」でつなぎます。かっこの外にあった「ではない」を中へ配ったら、「かつ」が「または」に変わりました。

この入れ替えを忘れると、4 通りある組み合わせのうち一部だけで答えが割れます。全部では割れないので、試した組み合わせが少ないと試験をすり抜けます。この回では、論理の演算を真理値表 (しんりちひょう、全部の組み合わせの答えを並べた表) で確かめ、否定を配る書き直しを、全部の行で確かめながら行えるようにします。

論理の演算とド・モルガンの法則はどう決まっているのか

論理の演算は、真 (True) と偽 (False) の 2 つの値だけを扱い、全部の組み合わせの答えを並べた真理値表で意味が決まります。ド・モルガンの法則も、その表の上で確かめられる決まりです。

AND、OR、NOT、XOR の真理値表

基本の演算は AND、OR、NOT の 3 つです。2 つが違うときだけ真になる XOR (排他的論理和) もよく使います。

演算読み方Python真になるとき
ANDかつ (論理積)a and b両方が真のときだけ
ORまたは (論理和)a or bどちらか 1 つでも真のとき
NOTでない (否定)not aa が偽のとき
XORどちらか一方だけa != b2 つが違うとき

OR は「どちらか一方だけ」ではありません。両方が真でも真です。日本語の「または」は、どちらか一方だけの意味で使うこともあるので、取り違えやすい所です。

and は両方が ON のときだけ電球が点き、or はどちらか 1 つでも ON なら点き、両方 ON でも点く図

否定を配るときは AND と OR を入れ替える

ド・モルガンの法則は、かっこの外の否定を中へ配るとき、AND と OR を入れ替えるという決まりです。式は次の 2 本です。

ド・モルガンの法則の 2 本

not (A and B)
  は (not A) or (not B)
not (A or B)
  は (not A) and (not B)

1 本目は「A かつ B、ではない」が「A でないか、B でないか」と同じという意味です。2 本目は「A または B、ではない」が「A でもなく、B でもない」と同じという意味です。

仕事のコードでは、冒頭の条件を次のように書き直すのに使います。

書き直す前

if not (logged_in and has_perm):
    deny()

書き直した後

if (not logged_in
        or not has_perm):
    deny()

どちらも「ログインしていない」か「権限が無い」なら断ります。

否定を配るとき AND と OR を入れ替える

集合で書くと、補集合と共通部分と和集合

ド・モルガンの法則は、集合 (ものの集まり) でも同じ形で成り立ちます。補集合 (ほしゅうごう) は、全体のうち、その集合に入っていない物の集まりです。「A の補集合」は「A でない物」の集まりなので、論理の NOT にあたります。

論理集合記号
NOT (でない)補集合A の上に横線
AND (かつ)共通部分A ∩ B
OR (または)和集合A ∪ B

この対応で読み替えると、「A と B の共通部分の補集合は、A の補集合と B の補集合の和集合」、「A と B の和集合の補集合は、A の補集合と B の補集合の共通部分」です。2 つの円を重ねたベン図で塗ってみると同じ所が塗られます。この頁では、図を塗る代わりに、全部の場合をコードで比べます。

3 つ以上でも、全部を入れ替えるだけ

条件が 3 つ以上でも、否定を配るときは、全部の AND を OR に (または全部の OR を AND に) 入れ替えます。

3 つのとき

not (A and B and C)
  は not A or not B or not C
not (A or B or C)
  は not A and not B and not C

「3 つの集合のド・モルガンの法則」と呼ばれるのはこの形です。2 つの場合をくり返し使うと、いくつになっても同じ形になります。

「すべて」と「ある」の否定

「すべての〜が真、ではない」は「ある〜が偽」と同じで、「ある〜が真、ではない」は「すべての〜が偽」と同じです。ド・モルガンの法則を、条件がいくつあっても使える形にした物です。

Python では、すべてが真かを all、1 つでも真があるかを any で調べます。次の 2 つの式は、同じ答えになります。

すべてとあるの否定

not all(xs)
any(not x for x in xs)

日本語の「全部は来なかった」と「全部来なかった」の違いも、この形です。「全部は来なかった」は「来なかった人がいる」(部分否定)、「全部来なかった」は「誰も来なかった」(全否定) です。

not は and より先に効く

Python では、not が and より先に、and が or より先に効きます。公式文書の演算子の優先順位の表で、Boolean NOT、Boolean AND、Boolean OR の順に並んでいます。

ですから not a and not b は (not a) and (not b) で、not (a and b) とは違う式です。かっこを省くと意味が変わる所なので、否定を配った式にはかっこを付けて読み直すと安全です。

動かして確かめる

1 本目は、AND、OR、NOT、XOR の真理値表を全部の組み合わせで作ります。itertools.product に [False, True] と repeat=2 を渡すと、2 つの値の組み合わせが全部出ます。1 は真、0 は偽です。

動かす 真理値表を作る

python実行可能
出力

▶ 実行ボタンを押すと結果がここに表示されます

実行すると、次の通りに出ます

A B and or notA xor
0 0   0  0    1   0
0 1   0  1    1   1
1 0   0  1    0   1
1 1   1  1    0   0

AND の列は最後の行だけが 1、OR の列は最初の行だけが 0 です。NOT は A の列をひっくり返しただけで、XOR は A と B が違う 2 行だけが 1 です。

2 本目は、ド・モルガンの法則の 2 本の式が、全部の組み合わせで左右同じになるかを比べます。条件が 2 つの場合と 3 つの場合の両方を数えます。

動かす ド・モルガンの確かめ

python実行可能
出力

▶ 実行ボタンを押すと結果がここに表示されます

実行すると、次の通りに出ます

2 つ 4 4
3 つ 8 8

条件が 2 つなら組み合わせは 4 通りで、4 通りすべてで左右が同じでした。3 つなら 8 通りで、8 通りすべてで同じでした。全部の組み合わせを見たので、「いつでも同じ」と言い切れます。これが真理値表を使った証明です。

3 本目は、「すべて」と「ある」の否定を確かめます。4 つの値の並びを全部 (16 通り) 作り、上の 2 つの式が同じかを数えます。空の並びも試します。

動かす すべてとあるの否定

python実行可能
出力

▶ 実行ボタンを押すと結果がここに表示されます

実行すると、次の通りに出ます

並び 16 同じ 16
空の all True
空の any False

16 通りすべてで同じでした。空の並びでは all が True、any が False です。「1 つも偽が無い」ので all は真になる、と読むと、ド・モルガンの法則と食い違いません。Python の公式文書も、all は空なら True、any は空なら False を返すと書いています。

どこで書き直しを間違えるのか

ド・モルガンの法則を使った書き直しで多い誤りは、AND と OR の入れ替えを忘れることです。忘れても半分の行では答えが合うので、気づきにくくなります。

入れ替えを忘れると 4 行のうち 2 行で割れる

not (login and perm) を書き直すとき、and を or に替え忘れて not login and not perm と書いたとします。login はログイン済みか、perm は権限があるかです。割れる行だけを出し、その数も数えます。

動かす 入れ替え忘れ

python実行可能
出力

▶ 実行ボタンを押すと結果がここに表示されます

実行すると、次の通りに出ます

True False True False
False True True False
割れた行 2

4 行のうち 2 行で答えが割れます。1 行目は「ログイン済みで権限が無い」場合で、正しい式は断る (True) のに、誤った式は断りません (False)。権限の無い人を通してしまう向きの誤りです。

両方とも真、両方とも偽の組み合わせでは答えが合います。「ログインして権限もある人」と「ログインしていない人」の 2 つしか試していない試験は、この誤りを通してしまいます。

書き直しても、呼ぶ順は変わらない

and と or は、左から調べて答えが決まったら右を調べません。これを短絡評価 (たんらくひょうか) と呼びます。Python の公式文書は、x and y はまず x を調べ、x が偽ならその値を返し、そうでなければ y を調べると書いています。

条件の中で関数を呼ぶと、書き直しで呼ぶ順が変わらないかが気になります。次のコードは、呼んだ関数の名前を記録して比べます。

動かす 呼ぶ順を比べる

python実行可能
出力

▶ 実行ボタンを押すと結果がここに表示されます

実行すると、次の通りに出ます

True True True AB AB
True False True AB AB
False True True A A
False False True A A

出力は左から、A、B、答えが同じか、左の式で呼んだ関数、右の式で呼んだ関数です。4 行すべてで答えが同じで、呼んだ関数も同じでした。A が偽の 2 行では、どちらの式も B を呼びません。左の式は「A かつ B」が A の時点で偽と決まり、右の式は「A でない」が真と決まるからです。ド・モルガンの法則で書き直しても、呼ぶ順と呼ぶ回数は変わりません。

かっこを外すと別の式になる

not a and b は、優先順位のとおり (not a) and b と読まれます。not (a and b) のつもりでかっこを省くと、別の式になります。上の入れ替え忘れと同じく、一部の行だけで割れます。否定を配ったら、その結果の式にもかっこを付けて書くと、読み違えが減ります。

書き直しは仕事でどう確かめるのか

論理の書き直しは、全部の組み合わせを回す試験で固めます。条件が n 個なら組み合わせは 2 の n 乗通りで、10 個でも 1,024 通りなので、全部を回せます。

書き直しを固める試験

from itertools import product

TF = [True, False]

def test_same_meaning():
    for a, b in product(
            TF, repeat=2):
        old = not (a and b)
        new = (not a) or (not b)
        assert old == new

new の or を and に替えると、この試験は割れる行で落ちます。

仕事では次の順で確かめます。

  1. 書き直す前の式を残し、新しい式と並べて、全部の組み合わせで同じ答えになる試験を書く
  2. 条件の中で関数を呼んでいるなら、呼ぶ順と呼ぶ回数も変わっていないかを見る
  3. 否定が 2 重になった所 (not not) や、!= と not が重なった所は、言葉で読み上げて意味を確かめる
  4. 権限の判定のように通すか断るかを決める式は、「通してはいけない人」の組み合わせを試験に必ず入れる

関わる実例

Linux の開発の倉庫に紛れ込んだ 1 行の条件 (2003年11月)

2003年11月6日、LWN.net は、Linux の開発版のソースを配る CVS の倉庫に、正規の手順を通らない変更が入れられたと報じました。変更は次の 1 行の条件でした。

if ((options == (__WCLONE|__WALL)) && (current->uid = 0))

ふつうの誤りの検査に見えますが、後半は current->uid を 0 と比べているのではなく、0 を代入しています。記事によると、wait4() をこの組み合わせの印で呼んだプログラムは、それ以後 root (管理者) の権限で動くことになり、典型的な裏口でした。変更はほかの変更にある記録の欠けから気づかれ、本流のカーネルには入りませんでした。

崩れた前提は「条件式は値を調べるだけで、何も変えない」です。C の && も Python の and と同じく、左が偽なら右を調べないので、代入は前半の組み合わせが当てはまったときにしか起きません。ふだんの呼び方では何も起きないので、組み合わせを絞った試験では見えません。条件式の中で値を変えないこと、組み合わせを全部回すことの 2 つが、この回の確かめ方につながります。

出典は An attempt to backdoor the kernel (LWN.net) です。

よくある問い

ド・モルガンの法則の覚え方はありますか

「否定を配ると、かつ と または が入れ替わる」の 1 文で覚えられます。「A かつ B、ではない」は、A と B のどちらか一方でも欠ければ当てはまるので「または」になる、と意味から考えると忘れにくくなります。迷ったら、上のコードのように 4 行の真理値表で確かめます。

「A かつ B」の反対は何ですか

「A でないか、B でないか (少なくとも一方でない)」です。「A でなく、B でもない」ではありません。後者は「A または B」の反対で、両方とも欠けたときだけを指します。

ド・モルガンの法則はどう証明するのですか

論理の式なら、真理値表で全部の組み合わせを並べ、左と右の値が同じかを比べれば証明になります。2 つの条件なら 4 通り、3 つなら 8 通りで、上のコードはその全部を数えました。集合なら、ベン図で左と右が同じ所を塗ることを確かめるか、「左に入る物は右に入り、右に入る物は左に入る」を両方向に示します。

ド・モルガンの法則はプログラミングで何に使うのですか

否定の入った条件式を、意味を変えずに読みやすい形へ書き直すときに使います。not (A and B) を not A or not B にすると、断る理由を 1 つずつ分けて書けます。if の中身を入れ替えるときや、while の続ける条件を止める条件に書き直すときにも使います。

3 つの場合のド・モルガンの法則は何ですか

not (A and B and C) は not A or not B or not C と同じ、not (A or B or C) は not A and not B and not C と同じ、の 2 本です。上のコードは、3 つの場合の 8 通りすべてで左右が同じことを確かめました。

確認クイズ

答えだと思う選択肢を押すと、その場で正誤と理由が開きます。4 問すべてに正しく答えると、この回は修了で、石が緑に変わります (この端末のブラウザに残ります)。間違えた問いは、あとから解き直せます。

1 問目

if not (logged_in and has_perm): と意味が同じ式はどれですか。

2 問目

「A または B、ではない」と同じ意味の文はどれですか。

3 問目

条件が 4 つある式で、ド・モルガンの法則による書き直しが正しいかを真理値表で全部確かめます。何通りの組み合わせを調べればよいですか。

4 問目

このコードを動かすと何が出ますか。

割れた行を数える

from itertools import product

bad = 0
TF = [True, False]
for a, b in product(
        TF, repeat=2):
    if (not (a or b)) != (
            not a or not b):
        bad += 1
print(bad)

説明課題

if not (is_member or is_admin): を、否定をかっこの中に配った形に書き直してください。そのうえで、書き直した式が元の式と同じ意味だと、どう確かめるかを 3 文以内で説明してください。書いたら、下の模範解答を開いて比べてください。

模範解答

自分の説明を書いてから開いて、比べてください。

この回の先の一歩

否定の入った条件は、ログインと権限の判定、入力の検査、検索の絞り込みなど、仕事のコードのあちこちにあります。書き直したら、全部の組み合わせを回す試験を足す習慣が、権限の穴を防ぎます。

もっと深く

この回の続きを、ゆめさくのコースの章や道具で深められます。頁の中の確認クイズに答えたあと、手を動かす量を増やしたいときに使ってください。

一次資料

どれも 2026年10月27日に開いて、題と中身を確かめました。

次へ

道 1 数と論理と計算量の回

  1. 1-12 進数と 16 進数桁の重み、変換、表せる範囲頁で読む
  2. 1-2文字コードと文字化けUnicode、UTF-8、Shift_JIS、BOM頁で読む
  3. 1-3計算量を数えるBig-O、ループの回数頁で読む
  4. 1-4論理と真理値表AND、OR、NOT、ド・モルガンこの回
  5. 1-5リトルエンディアンとビッグエンディアンバイトの並び順、ネットワーク、ファイル頁で読む
  6. 1-6Base64 の仕組み64 字の表、= の詰め物、長さ 4/3頁で読む
  7. 1-7情報量とハフマン符号化ビット、確からしさ、圧縮頁で読む
  8. 1-8チューリングマシンと停止問題テープ、状態、計算できない問題頁で読む

道 1 の頁へ戻るほかの道を見る