真か偽か、それが問題だ。〈ブール値編〉【ITの正体見たり#1】

今回の内容はプログラミング色が強めです。が、未経験者にも分かりやすく解説してまいります。

このシリーズでは、実は身近な話題に関連している IT(情報技術)を解説していきたいと思います。

ブール値とは

プログラミングにおける真か偽の値のことです。真理値、論理値、真偽値などとも呼ばれています。待って難しくないから帰らないナイデ。

まず、プログラミングでは、 という概念を扱います。といっても大層なものではなく、これは数値、これは文字、これは日時のように、何を表す値であるかを明確にしておくといっただけです。表計算ソフトを使ったことのある方ならば、数値と文字列は別物だというイメージを持ちやすいかもしれません。あるいは、数学で「x は実数である」などと宣言するのにも近いかもしれません。

そして、true)またはfalse)を表すデータ型 (=ブール型,Boolean)の値のことを特にブール値と呼んでいます。要するに真か偽かのことです。例えば条件分岐をさせたい時などは、答えがブール値になるような式1を書き、その真偽に応じて分岐するプログラムを組んでやるわけです。

実例を挙げましょう。以下は実際に JavaScript2 において実行可能なプログラムです。

let x = 3; // x に 3 を代入する

if (x < 5) { // x が 5 未満なら
  alert("This is true!"); // "This is true!" と表示する
}
JavaScript

ここで注目してほしいのが3行目の括弧の中の部分です。今回はx < 5という答えがブール値になる式を書き入れましたが、もしここに数値や文字列といったブール値以外の値を入れたらどうなるでしょうか。

当然ながら、これらはブール値ではないのでエラーが発生する…と言いたいところですが、多くのプログラミング言語ではこれを単なるエラーとして扱わず、都合が良い解釈で判定することになっています。

いくつか例を挙げましょう。以下は Python3 の仕様に従います。

真(true)と解釈される値

  • True(ブール値)
  • 1(数値)
  • -999(数値)
  • "fuku"(文字列)
  • "木枯"(文字列)
  • "False"(文字列)

偽(false)と解釈される値

  • False(ブール値)
  • 0(数値)
  • ""(空文字列)
  • [](空のリスト)
  • set()(空の集合)

TrueFalseはそのままですね。0が偽なのは、コンピューターの内部で真と偽をそれぞれ 1 と 0 で表現することに由来します。ですが、多くの言語では1以外にも(0を除く)すべての数値を真と扱うことが多いようです。現代でも 0 は特別な値ということでしょうか。

続いて、文字列についてですが、空文字(=0文字の文字列、表計算ソフトで未入力のセルに近い)は偽、それ以外はすべて真として扱います。つまり、文字列の"False""偽"も真なのです。直感に反するかもしれませんが、これは実例を考えると当然のことなのです。

まず、どんな時にプログラマーはこの文字列の真偽に依存するプログラムを書くでしょうか。例えば、ユーザーに名前を入力するように促し、名前がきちんと入力されていれば正常に処理を行い、なにも入力されていなければエラーメッセージを表示するといったプログラムを考えます。これを実際のプログラミング言語で書くと以下のようになります。

name = input("Enter your name> ") # ユーザーに名前を入力するように促す

if name != '': # もし名前が空文字でない(名前が入力された)とき
  do_something() # なにか正常な処理を行う
else: # そうでなければ(名前が入力されていないとき)
  print("Error! Name is not entered.") # エラーメッセージを表示する
Python

ここで3行目に注目してください。ここの条件name != ''4は「名前が空文字でない」ことですが、これは前述の仕様によりもっと単純にnameと書けるのです。

name = input("Enter your name> ") # ユーザーに名前を入力するように促す

if name: # もし名前が空文字でない(名前が入力された)とき
  do_something() # なにか正常な処理を行う
else: # そうでなければ(名前が入力されていないとき)
  print("Error! Name is not entered.") # エラーメッセージを表示する
Python

論理演算子

ちょいと話を脱線させて、次は論理演算子の話をしましょうか。名前がややこしいですが、要は我々が日常でよく使う「または」や「かつ」などのことです。英語で言うところの AND や OR などに相当しますね。

また Python で例を挙げましょう。Python では"または"をor、"かつ"をandで表現します。つまり以下の関係が成り立つわけですね

False and FalseFalse
False and TrueFalse
True and FalseFalse
True and TrueTrue
論理演算子and
False or FalseFalse
False or TrueTrue
True or FalseTrue
True or TrueTrue
論理演算子or

ではここで問題です。2 and 3の値は何になるでしょうか。また、2 or 3はどうでしょうか。

答え(クリックで開く)

2 and 33。また、2 or 32になる。

予想は合っていましたか?ちょっと意地悪でしたかね。でもこれにはちゃんと訳があるのです。

まずは前提となる、ある種当たり前の話をしましょう。

コンピューターはとても高速に計算を行いますが、それでも早いに越したことはありません。なので、無駄な計算はしたくありません。ここでA and Bが真、つまりAB両者が真のときにのみ実行する処理Xがあるとします。ここで、Bの値を求めるのはとても大変で、できればやりたくないとしましょう。このとき、Aの値が偽であると分かったとしましょう。ならばBの値をどうして求める必要がありましょうか。どうせAが偽なら処理Xを実行することは無いのですから。この計算の省略のことをショートサーキットと呼んだります。

ここまでの話をまとめると、A and Bの内部処理は以下のように簡略化できそうです。

改良前

graph TD; is-a{A が真である} is-a --"真"--> is-b1{B が真である} is-b1 --"真"--> true["答えは True"] is-b1 --"偽"--> false["答えは False"] is-a --"偽"--> is-b2{B が真である} is-b2 --"真"--> false is-b2 --"偽"--> false

改良後

graph TD; is-a{A が真である} is-a --"真"--> is-b{B が真である} is-b --"真"--> true["答えは True"] is-a --"偽"--> false["答えは False"] is-b --"偽"--> false

ここで改良後の「B が真である」の部分に注目してください。なんとBの真偽とA and Bの真偽が一致しているではありませんか!よってさらに以下のように改良できそうです。(ついでに「B が偽である」の部分もそれに倣って修正。)

graph TD; is-a{A が真である} is-a --"真"--> is-b["答えは B(と同じ)"] is-a --"偽"--> false["答えは A(と同じ)"]

これが2 and 33になる理由です。2は真ですから、Bである3という値がそのまま帰ってきてしまっているのです。

同様の省略により、A or Bの内部処理は以下のようになっています。

graph TD; is-a{A が真である} is-a --"真"--> true["答えは A(と同じ)"] is-a --"偽"--> is-b["答えは B(と同じ)"]

時間がある方はABそれぞれに真偽を入れて確かめてみてください。

ブール値を返す関数

では第二問目です。Python にはリストの中身すべてが真の時にのみTrueになる関数all(iterable)があります。いくつか動作の例を挙げましょう。

  • all([True, True, True])True
  • all([True, False, True])False
  • all([False, False, False])False
  • all([True])True

ではここで問題です。all([])は真偽どちらでしょうか。要するに、空っぽのリストの中身はすべて真といえるでしょうか。

答えと解説(クリックで開く)

答えはTrueです。「リストの中身すべてが真の時」は言い換えると「リストの中身に偽が一つも無いとき」です。あるいは、「ある集合がこの条件を満たすとき、その集合の部分集合もこの条件を満たす」という説明も出来るかもしれません。空集合は任意の集合の部分集合ですからね。

  1. プログラミングでは、x + 3のように答えが数値になる式のほかに、x < 5のような答えがブール値になる式なども扱います。 ↩︎
  2. Webサイトなどで使われるプログラミング言語。 ↩︎
  3. 読みやすさを意識して作られたプログラミング言語。 ↩︎
  4. !=は左辺と右辺が異なる値のとき真になる不等価演算子と呼ばれるものです。 ↩︎
Verified by MonsterInsights