ブーリアン型




ブーリアン型(ブーリアンがた、英: Boolean datatype)は、真理値の「真 = true」と「偽 = false」という2値をとるデータ型である。ブーリアンブール型論理型(logical datatype)などともいう。2種類の値を持つ列挙型とも、2進で1ケタすなわち1ビットの整数型とも、見ることもできる。


また、各種ブール演算を行うことができ、論理積 (AND, &, *)、論理和 (OR, |, +)、排他的論理和 (XOR, NEQV, ^)、同値 (EQV, =, ==)、非同値 (NEQV, <>, !=)、否定 (NOT, ~, !) などの操作が可能である。これらの演算はブール代数の演算に対応している。




目次






  • 1 Ada


  • 2 ALGOL


  • 3 C言語


    • 3.1 C99


    • 3.2 ステータスコードと真偽値




  • 4 C++


    • 4.1 vector<bool>




  • 5 C#


  • 6 Dart


  • 7 ECMAScript


  • 8 FORTRAN


  • 9 Haskell


  • 10 Java


  • 11 JavaScript


  • 12 Lisp


    • 12.1 Scheme




  • 13 ML


    • 13.1 OCaml




  • 14 Pascal


  • 15 Perl


  • 16 Python


  • 17 PHP


  • 18 Ruby


  • 19 Smalltalk


  • 20 Visual Basic


  • 21 VB.NET


  • 22 脚注





Ada


Ada では、BooleanStandard パッケージにあり、False および True という値をとる列挙型として定義されている。ここで、False < True である。


type Boolean is (False, True);

p : Boolean := True;
...
if p then
...
end if;

比較演算子(=, /=, <, <=, >, >=)は Boolean を含めた全ての列挙型に適用可能である。ブール演算子 andorxornotBoolean について定義されており、その派生型にも適用可能である。ブール演算子は Boolean の配列にも適用可能である。



ALGOL


Algol 60 にはデータ型として Boolean が定義されており、演算子も定義されている。なお、ALGOL 68 ではデータ型の名称が bool に短縮された。



C言語


C言語ではブーリアン型はintで代用されることが多い(C99の _Bool型とシンボルについては後述する)。移植性・相互運用性の向上や集成体のサイズ削減の観点から、型サイズが常に1バイトのunsigned charで代用されることもある(JNIヘッダー<jni.h>のjboolean型、COMヘルパー<rpcndr.h>のboolean型など)。


通例、値が 0 であれば偽であり、それ以外は真である。ただし論理否定演算子!による !0 のような式は、真の値の代表値として 1 を返すと標準規格で決められている。他に、ヌルポインタや浮動小数点数 0.0 のような、定数 0 と同様の値が偽として扱われる。


真と偽の値に名前を付けて意味を明確にする際に、列挙型を使う方法もあるが、実際はプリプロセッサマクロが使われていることのほうが多い(Windows APIなど)。


typedef enum boolean { FALSE, TRUE } boolean_t;
...
boolean_t b = TRUE;

#define FALSE 0
#define TRUE 1
typedef int boolean_t;
...
boolean_t f = FALSE;

列挙型のほうが、型とその型の変数に代入してよい定数との対応が分かりやすい。デバッガの実装および利用時に関しても、マクロシンボルよりも列挙型のほうが有利である。また、プリプロセッサマクロは名前衝突時に予期せぬ動作を引き起こすこともある。いずれにしても、C99では標準で定義されたものがあるし、そうでなくても大抵の環境では処理系標準ライブラリなどのヘッダーファイル内で同様のシンボルが定義されていることが多いため、プログラマがユーザーコードで明示的に定義する必要はほとんどない。


なお、こういったシンボルを定義した場合、TRUE は代入のためのみに用い、(cond == TRUE) のように比較に使用してはならない。cond の値が0でもなく1でもないとき、C言語としての意味では真であるにもかかわらず、TRUEとの比較判定式は偽になることで混乱や不具合を招くからである。



  • 正しい例: if (cond) {...}, if (!cond) {...}, if (cond != FALSE) {...}, if (cond == FALSE) {...}

  • 誤った例: if (cond == TRUE) {...}, if (cond != TRUE) {...}

  • 好ましくない例: if (i < 0 == TRUE) {...}, if (i < 0 != TRUE) {...}, if (i < 0 == FALSE) {...}, if (i < 0 != FALSE) {...}


そもそも、(条件 == TRUE) という表現は無意味に冗長であり、単に (条件) と書くべきである。もし、(条件 == TRUE) と書くことが何かを明示していて良い表現だというのなら、...(((条件 == TRUE) == TRUE) == TRUE) == TRUE... は、もっと良い表現だということになる(次を参照のこと http://www.kouno.jp/home/c_faq/c9.html#2 、亀がアキレスに言ったこと)。



C99


C99ではブーリアン型を格納したりするための型が作られ、その型のためのキーワード _Bool が追加された。さらにその型と値のためにシンボル bool, false, true が、<stdbool.h> というヘッダファイルで定義される。


#include <stdbool.h>
bool b = false;
...
b = true;

条件式の型などの意味は、C99でも変わっていないので注意すること。



ステータスコードと真偽値



0が偽、0以外が真というルールは、C言語文化圏で必ずしもいつもそうとは限らず、ライブラリやフレームワークによっては別のルールの場合もある。C言語文化圏で最も顕著な例はUnix等における終了ステータスの慣習であろう。正常を示す0が真、異常を示す0以外の残り全てが偽(エラーコード)という扱いであり、シェルのコマンド行中の &&|| は終了ステータスの値をそのように扱って短絡評価の動作をする。これは、異常については「何が起きたのか」といったような情報が必要なことが多いため、といったような理由がある。



COMのステータスコードとして使われる32ビット整数のHRESULT型は、ゼロを成功(S_OK)、正数を準成功(S_FALSE: 失敗ではないが否定的な状態[1])、負数を失敗(E_FAILなど)、とみなす。成否の判定のためにSUCCEEDED()/FAILED()マクロが用意されている。


C11で標準化されたerrno_t型はゼロを正常(エラーなし)とみなす[2]


また、比較などで「小なり」「等しい」「大なり」の3通りの意味を返したい、といった場合には、負の値・ゼロ・正の値、とするのが自然であるため、たとえば代表例の strcmp() 関数では、文字列が等しいということを示すためにゼロが返される。なお、単に「文字列が等しいか?」という比較を連続している場合などに、論理否定演算子!を使用したコードは一見不自然に見えるため、あえて(strcmp(s1, s2) == 0)と記述することで分かりやすさを向上する方法もある。


if ( ! strcmp(cmd, "hello")) {
say_hello();
} else if ( ! strcmp(cmd, "hi")) {
say_hi();
...
...
} else if ( ! strcmp(cmd, "bye")) {
exit();
}


C++


C++では、標準化の過程で booltruefalse というキーワードが導入され、基本データ型としてサポートされた。その大きさは処理系で定義される。


ブーリアン型を出力するコードは以下のようになる。


int i = 5;
bool myBool = (i == 5);
std::cout << "i == 5 is " << std::boolalpha << myBool << std::endl;

boolalphaはbool型の値の出力をtrueまたはfalseにするマニピュレータであり、省略すると1または0が出力される。



vector<bool>


ISO C++ 1998の標準C++ライブラリでは、vector<bool>クラスが定義されている。メモリ使用量を最適化するため、各ブール値は1ビットに格納される。しかし、vector<bool>はSTLコンテナの要求には合致しないため、これをvectorの特殊化に含めてしまったのは仕様策定上のミスだと言われている(標準化委員会ではstd::vector_boolにするべき等の意見があった)。これは動的なビット集合として使うには非常に適しているが、vector<bool>という名前から連想されるようなSTLのコンテナとしての挙動はしないので、そういう意味では注意が必要である。



C#


C#では、ブーリアン型は bool である。これは.NETのSystem.Boolean型のエイリアスであるが、Marshal.SizeOf()sizeof演算子の結果はそれぞれ異なる[3]


Console.WriteLine(typeof(bool)); // System.Boolean
Console.WriteLine(System.Runtime.InteropServices.Marshal.SizeOf(typeof(bool))); // 4
Console.WriteLine(sizeof(bool)); // 1
bool b = true;
Console.WriteLine(Convert.ToInt32(b)); // 1

ブーリアン型を出力するコードは以下のようになる。


int i = 5;
bool myBool = (i == 5);
System.Console.WriteLine("i == 5 is " + myBool);

この出力結果は次の通り。


i == 5 is True


Dart


Dartでは、dart:core ライブラリに bool クラスがあり、true と false がそれの真偽値(とそのリテラル)である。(「他の多くの値は真として扱われる」という、他の多くの言語と違い)true 以外は全て偽として扱われる。さらに checked mode では、if文など真偽値が必要とされる場所では型チェックがされるため、他の型の値であった場合は型チェックでエラーになる。



ECMAScript




FORTRAN


キーワード LOGICAL と演算子 .NOT..AND..OR. などが1950年代に導入された。これはFORTRANが標準化される以前のことである。



Haskell


Haskell では data Bool = False | True のように定義される型であり、Bounded Enum Eq Ord Read Show などの型クラスのインスタンス型である。not・&&・|| といった関数と演算子がある。



Java


Javaでは、ブーリアンはプリミティブ型で boolean である。整数型からbooleanへの、あるいはbooleanから整数型への暗黙の型変換は無い。


以下のようなコードはコンパイル時エラーとなる。


int i = 5;
if (i = 5) System.out.println("i is five"); // i == 5 の間違い。
if (i) System.out.println("i is not zero");

上記の例において、式 i = 5i の結果はintと評価されるが、Javaのif文の条件式はC/C++と違いbooleanのみを受け付けるためコンパイルエラーとなる。


ブーリアン型を出力するコードは以下のようになる。


boolean myBool = (i == 5);
System.out.println("i == 5 is " + myBool);

この出力結果は次の通り。


i == 5 is true

boolean のプリミティブラッパークラスは Boolean である。



JavaScript


JavaScriptにはBoolean型があり、それの真偽値(とそのリテラル)は true と false である。比較演算などの結果はBooleanの値になるが、論理演算子 && や || は引数を次で示すように扱って短絡評価し、結果はどちらかの引数の値となる。JavaScriptでは論理演算子やif文など真偽を必要とする場合に、それが真として扱われること(真となる値)を truthy(真値っぽい)、偽として扱われること(偽となる値)を falsy(偽値っぽい)と言う[4][5]。代表値 false の他、Undefined型の値、Null型の値、数値の 0 と −0 と NaN、空文字列( "" )、以上の値が falsy であり、代表値 true の他、以上で述べた falsy である値以外の全ての値が truthy である。


なお標準仕様であるECMAScriptの規格票ではそのような用語を使わず、真偽値を評価する場所では §7.1.2(ECMA-262 7th Edition の場合)で示されている ToBoolean という操作を使って true か false かを得るといったように記述されている。



Lisp


Lispでは、近年のSchemeのように大きく異なる方言も多いが(Schemeについては後述)だいたいのLispでは、他の言語のnullに相当するnilというシンボルが特殊なシンボルで、nullのような意味の他、空リスト'()や偽の代表値でもある(同じものであるか、同一視される)。それ以外は全て真として扱われる。真の代表値としてtという特殊なシンボルがある。



Scheme


Schemeでは真偽値は #t#f であり、if などでは #f 以外のあらゆる値(特に、空リスト '() も)が真として扱われる。



ML


ML には bool 型があり、値として truefalse をとる。以下に例を示す。


- fun isittrue x = if x then "YES" else "NO" ;
> val isittrue = fn : bool -> string
- isittrue true;
> val it = "YES" : string
- isittrue false;
> val it = "NO" : string
- isittrue (8=8);
> val it = "YES" : string
- isittrue (7=5);
> val it = "NO" : string


OCaml


OCamlも bool 型を持ち、値として truefalse をとる。


# 1 = 1 ;;
- : bool = true


Pascal


Pascalでは、Boolean は基本データ型として提供されている。以下に例を示す。


var
value: Boolean;

...

value := True;
value := False;

if value then
begin
...
end;

なお、PascalをベースにしたDelphi言語(Object Pascal)には、Boolean 型の他に ByteBool 型(1バイト論理型)、WordBool 型(2バイト論理型)、LongBool 型(4バイト論理型)が存在する。



Perl


Perlでは、集合型でないデータ型である数や文字列には区別がない(すべてスカラーと呼ばれる)。ブール演算では、要素を持たない集合型、空の文字列、値が 0 と等しい数値、文字列 """0"、未定義変数が "false" と解釈される。これら以外の全ての値は "true" と解釈される(例えば 0.0 とか 0E0 といった文字列は「0 だが true」となる)。


集合型の要素は、存在するかしないかを評価されることもあり[6]、全ての変数は定義されているかいないかを評価されることがある[7]。ハッシュや配列の要素で値が undef であるものは、存在しているが未定義である。存在と定義の区別は、スカラーをブーリアンのように扱う際に重要である。


Perl 5 では真理値を表す定数は組み込まれていないが、Perl 6 では存在している。



Python


Pythonでは、以下のような値が偽として扱われる。他は真として扱われる。



  • 数値型の 0、None、False。

  • 組み込みのコンテナ型の空のオブジェクト。例えば空の文字列、空のリスト、空のタプル。

  • 空の辞書と空の集合。

  • ユーザー定義オブジェクトで、特殊メソッド __nonzero__[8] (Python3の場合__bool__) または __len__ により、自身のブール値に対して制御を持ち、以上のような偽の値を返すもの。


Ruby等に慣れていると最後のようなオブジェクトの扱いを間違えることがあるので注意が必要である。


定数 FalseTrue は Python 2.2.1 でビルトインに追加された。bool 型は Python 2.3 で追加された。


比較演算などは True または False を返す。"or" や "and" は短絡評価によりオペランドの1つを返す。


>>> class spam: pass    # spam にクラスオブジェクトを代入
...
>>> eggs = "eggs" # eggs に文字列オブジェクトを代入
>>> spam == eggs # (等しいかどうかの判定)
False
>>> spam != eggs # != と == はブール値を返す
True
>>> spam and eggs # and はオペランドを返す。
'eggs'
>>> spam or eggs # or もオペランドを返す。
<class __main__.spam at 0x01292660>
>>>


PHP


PHPの bool型はPythonとほぼ同じで、値として TRUEFALSE が定義されており、0やNULLと同じような値は概ね FALSE と見なされる。



  • 数値の0、0.0、NULL

  • FALSE、False、false

  • 空の文字列、文字列の "0"、空の配列

  • 定義されていない変数

  • (PHP4のみ)空のオブジェクト


等はFALSEと見なされる。
また、比較方法によっては厳密な比較を行うこともできる。


$a = 0;
print ( $a == false ); //trueと評価される
print ( $a === false); //falseと評価される

print ( "0" == 0 ); //trueと評価される
print ( 0 == "" ); //trueと評価される
print ( "0" == "" ); //falseと評価される 緩やかな比較では推移律が成り立たない場合がある


Ruby


Rubyにはブーリアン型に相当するようなクラスは無く、falseFalseClassクラスのインスタンス、trueTrueClassクラスのインスタンスである。真偽値としては、falsenil 以外は全て真として扱われるので、空文字列や数値の 0 が偽として扱われる言語に慣れた者や移植の際は注意が必要である。


a = 0
if (a)
print "true"
else
print "false"
end

このコードは "true" を表示する。


nilもオブジェクトであり、NilClassクラスのインスタンスである。


p false.class
p true.class
p nil.class

とした場合、それぞれ "FalseClass"、"TrueClass"、"NilClass" が出力される。



Smalltalk


SmalltalkではtrueTrueクラスのオブジェクト[9]falseFalseクラスのオブジェクト[10]で、TrueクラスとFalseクラスはそれぞれBooleanクラスを継承したクラスになっている。Smalltalkには言語機能としてif文にあたる構文が無くTrueクラスとFalseクラスの違いによって分岐を実現している。


value := true ifTrue: [ 1 ] ifFalse: [ 0 ].

上記はif文にあたる分岐の例でtrueに分岐用のメッセージを送っているため前者のブロックを評価しvalueに1を代入している。
メッセージ送信側だけでは他の言語におけるif文の糖衣構文にしか見えないが書き方はSmalltalkにおける一般的なメッセージ式に過ぎず、クラスにも下記のようにメッセージに対応するメソッドが存在する。


True methodsFor: 'basic'
!
ifTrue: aTrueBlock
ifFalse: aFalseBlock
^ aTrueBlock value.
!!

Smalltalkにおけるブール値はこのような構造になっているため、原則として他の言語の様に数値との相互変換が存在しない。ただし、#ifTrue:ifFalse:を実装したオブジェクトとの互換性を持つ。ただし処理系によっては性能維持のため#ifTrue:ifFalse:の引数にブロック指定した場合はtrueかfalseでなければ例外を出すなど互換性が若干制限されている場合もある。
また、Smalltalkではnilも同様に分岐として振る舞うことができ、nilと組み合わせることで3値論理として使うこともできる。


nil ifNotNil: [ :value | value ifTrue:  ifFalse:  ].


Visual Basic


Visual Basic には Boolean 型があり、比較演算の結果はこの型となる。16ビット(2バイト)の整数として格納されるが、値は True(-1)False(0) しかない。以下に例を示す。


Dim isSmall As Boolean
isSmall = intMyNumber < 10 ' 式を評価した結果は True か False となる
If isSmall Then
MsgBox("The number is small")
End If

Dim hellFreezesOver As Boolean ' Boolean 変数は False で初期化される
hellFreezesOver = False ' あるいは、代入文を使うこともできる
Do Until hellFreezesOver
Call CheckAndProcessUserInput()
Loop

なお、OLE/COM、特にOLEオートメーションで使用される論理型 VARIANT_BOOL も、Visual Basic の Boolean 型と同一である。VARIANT_TRUEおよびVARIANT_FALSEは<wtypes.h>にて以下のように定義されている。


typedef short VARIANT_BOOL;
#define VARIANT_TRUE ((VARIANT_BOOL)-1)
#define VARIANT_FALSE ((VARIANT_BOOL)0)


VB.NET


Visual Basic .NET (VB.NET) のBoolean型はSystem.Booleanのエイリアスであるが、オリジナルのVBと類似の振る舞いをする[11]


Console.WriteLine(GetType(Boolean)) ' System.Boolean
Console.WriteLine(System.Runtime.InteropServices.Marshal.SizeOf(GetType(Boolean))) ' 4
Dim b As Boolean = True
Console.WriteLine(Len(b)) ' 2
Console.WriteLine(CType(b, Integer)) ' -1


脚注




  1. ^ Error Handling in COM | Microsoft Docs


  2. ^ エラー処理 - cppreference.com


  3. ^ sizeof (C# リファレンス) | Microsoft Docs


  4. ^ Truthy


  5. ^ Falsy


  6. ^ exists - perldoc.perl.org


  7. ^ defined - perldoc.perl.org


  8. ^ “Special method names: Basic customization”. Python Language Reference. 2008年2月3日閲覧。[リンク切れ]


  9. ^ “GNU Smalltalk Library Reference: True”. www.gnu.org. 2018年6月28日閲覧。


  10. ^ “GNU Smalltalk Library Reference: False”. www.gnu.org. 2018年6月28日閲覧。


  11. ^ Boolean Data Type (Visual Basic) | Microsoft Docs





Popular posts from this blog

Accessing regular linux commands in Huawei's Dopra Linux

Can't connect RFCOMM socket: Host is down

Kernel panic - not syncing: Fatal Exception in Interrupt