0はなぜ偽ですか?


115

この質問は馬鹿げているように聞こえるかもしれませんが、ほとんどのプログラミング言語が0評価されfalse、他の[整数]値が評価されるのはなぜtrueですか?

文字列比較

質問は少し単純すぎるように思えるので、もう少し説明します。まず、プログラマーにとっては明白に思えるかもしれませんが、なぜプログラミング言語がないのか-実際にはあるかもしれませんが、私は使用しました-どこに0評価しtrue、他のすべての[整数]値を評価しfalseますか?その発言はランダムに見えるかもしれませんが、私はそれが良いアイデアだったかもしれないいくつかの例を持っています。まず、文字列の3者間比較の例を取り上げましょstrcmpう。Cを例に取ります。C 言語を最初の言語として試すプログラマーは、次のコードを書きたくなるかもしれません。

if (strcmp(str1, str2)) { // Do something... }

文字列が等しいときに評価されるstrcmp戻り値なので、最初のプログラマーがやろうとしたことは惨めに失敗し、一般的に最初はなぜか理解できません。していたために評価上記1 - -代わりに、この関数はその最も単純な式で使用されている可能性が平等を比較するとき、およびのための適切なチェックとは、必要なときにのみ行われていたであろう。ほとんどの場合、戻り値の型を(私たちの考えでは)考えていたでしょう。0false0true-11bool

さらに、sign-10およびのみを受け取る新しいタイプを導入しましょう1。それはかなり便利です。C ++に宇宙船オペレーターがあり、それを望んでいると想像してくださいstd::string(まあ、既にcompare関数はありますが、宇宙船オペレーターはもっと楽しいです)。現在、宣言は次のようになります。

sign operator<=>(const std::string& lhs, const std::string& rhs);

していた0ために評価されtrue、宇宙船演算子は存在さえしないだろう、と私たちは宣言している可能性がoperator==そのように:

sign operator==(const std::string& lhs, const std::string& rhs);

これoperator==は3者間比較を一度に処理し、必要に応じてどの文字列が辞書的に優れているかを確認しながら、次のチェックを実行するために使用できます。

if (str1 == str2) { // Do something... }

古いエラー処理

現在、例外があるため、この部分は、そのようなものが存在しない古い言語(Cなど)にのみ適用されます。Cの標準ライブラリ(およびPOSIXのライブラリ)を見ると、maaaaany関数0が成功すると必ず戻り、それ以外の整数は必ず戻ります。悲しいことに、このようなことをする人を見たことがあります。

#define TRUE 0
// ...
if (some_function() == TRUE)
{
    // Here, TRUE would mean success...
    // Do something
}

プログラミングの考え方を考えると、次のような推論パターンがよくあります。

Do something
Did it work?
Yes ->
    That's ok, one case to handle
No ->
    Why? Many cases to handle

私たちはもう一度考えてみれば、それは、唯一の中立値を入れることに意味をなされているだろう0、とyes(それはCの関数がどのように動作するかだ)他のすべての値は、多くの例を解決するために存在することができますが、no。ただし、私が知っているすべてのプログラミング言語(いくつかの実験的なエサトリック言語を除く)では、条件でyes評価さfalseれ、ifすべてのnoケースで評価されtrueます。「機能する」が1つのケースを表し、「機能しない」が多くの考えられる原因を表す場合が多くあります。そのように考えれば、0評価しtrueて残りを評価した方falseがずっと理にかなっているでしょう。

結論

どこなぜ我々は、言語を設計しました:私の結論は、基本的に私の元の質問で0ありfalse、その他の値はtrue私のいくつかの例を超えると、多分私はいくつかのより多くの考えていなかったアカウントに取って、?

フォローアップ:多くのアイデアと多くの考えられる理由があり、それがそのようになる理由はたくさんあります。あなたがそのことに情熱を傾けているように見えるのが大好きです。私はもともと退屈からこの質問をしましたが、あなたはとても情熱的に思えるので、少し進んで、Math.SEの0と1のブール選択の背後にある理論的根拠について尋ねることにしました:)


32
strcmp()3つの異なる値を返すため、trueまたはfalseの良い例ではありません。そして、シェルの使用を開始すると驚かれます。0はtrueを意味し、それ以外はfalseを意味します。
ott--

52
@ ott--:Unixシェルでは、0は成功を意味し、0 以外は失敗を意味します。「true」および「false」とまったく同じではありません。
キーストンプソン

14
@KeithThompson:Bash(および他のシェル)では、「成功」と「失敗」は実際には「true」と「false」と同じです。たとえば、ステートメントを考えてみましょう。if true ; then ... ; fiここtrueで、はゼロを返すコマンドで、これはifrunを指示します...
-ruakh

13
ハードウェアにはブール値は一切なく、2進数のみであり、ほとんどの歴史的なISAでは、ゼロ以外の数値はすべての条件分岐命令で「真」と見なされます(代わりにフラグを使用している場合を除く)。そのため、低レベルの言語は、必ず基礎となるハードウェアのプロパティに従う必要があります。
SKロジック

2
@MasonWheelerブール型を持つことは何も意味しません。例えば、Pythonはありません持っているboolなどの条件は任意の戻り値を持つことができるかどうかのタイプが、比較を/。
バクリウ

回答:


98

0それはfalse、それらが共通の半環の両方のゼロ要素だからです。それらは別個のデータ型ですが、同型代数構造に属しているため、それらの間で変換することは直感的です。

  • 0は加算のアイデンティティであり、乗算のゼロです。これは、整数と有理数のための真のですが、ない IEEE-754浮動小数点数:0.0 * NaN = NaN0.0 * Infinity = NaN

  • falseは、ブールxor(⊻)のアイデンティティであり、ブールand(∧)のゼロです。ブール値が{0、1}(2を法とする整数のセット)として表される場合、⊻はキャリーなしの加算、thinkは乗算と考えることができます。

  • ""及び[]連結のためのアイデンティティがありますが、それらはゼロとして理にかなっているいくつかの操作があります。繰り返しは1つですが、繰り返しと連結は分散しないため、これらの操作は半環を形成しません。

このような暗黙の変換は、小規模なプログラムでは役立ちますが、大規模なプログラムでは、プログラムの推論が難しくなります。言語設計における多くのトレードオフの1つにすぎません。


1
リストについて言及してくれてうれしいです。(ところで、Common Lisp nilの空のリスト[]false値の両方です;異なるデータ型のアイデンティティをマージする傾向がありますか?)あなたはまだfalseを加算アイデンティティとして、trueを乗法的アイデンティティとして考えるのが自然である理由を説明する必要があります逆ではありません。trueの識別ANDおよびゼロと見なすことはできませんORか?
ジョルジオ

3
+1は、同様のIDを参照するためのものです。最後に、「慣習、それに対処する」だけに要約されない答え。
l0b0

5
+1が具体的で非常に古い数学の詳細を説明してくれたため、これが守られ、長い間理にかなっていた
ジミーホファ

1
この答えは意味がありません。true半環のアイデンティティとゼロでもあります(ブールおよび/または)。appartの慣習では、考慮するfalseよりも0に近い理由はありませんtrue
-TonioElGringo

1
@TonioElGringo:trueとfalseの違いは、XORとXNORの違いです。AND / XORを使用して同型リングを形成できます。ここで、trueは乗法恒等式であり、falseは加法恒等式です。 XORと同様の基本操作。
-supercat

74

数学が機能するからです。

FALSE OR TRUE is TRUE, because 0 | 1 is 1.

... insert many other examples here.

従来、Cプログラムには次のような条件があります。

if (someFunctionReturningANumber())

のではなく

if (someFunctionReturningANumber() != 0)

ゼロが偽に等しいという概念はよく理解されているからです。


21
数学が理にかなっているので、言語はそのように設計されています。それが最初に来ました。
ロバートハーヴェイ

26
@Morwenn、それは19世紀とジョージ・ブールに遡ります。人々は、Falseを0として、Trueを!0として、これまでのコンピューターよりも長い間表現してきました。
チャールズE.グラント

11
ANDが+でORが*になるようにすべての定義を変更しただけでは、数学が他の方法で機能しない理由はわかりません。
ニールG

7
正確に:数学は両方の方法で機能し、この質問に対する答えは、純粋に慣習的なものであるようです。
ニールG

6
@Robert投稿で「数学的な基盤」を詳しく説明できたら素晴らしいと思います。
phant0m

38

他の人が言ったように、数学が最初に来ました。これが0がfalse1である理由ですtrue

私たちはどの数学について話しているのですか?デジタルコンピューターが登場するずっと前の、1800年代中頃のブール代数

また、慣習は命題論理から生まれたと言うこともできます。これはブール代数よりも古いものです。これは、プログラマーが知っていて愛している多くの論理的な結果(false || x等しいxtrue && x等しいxなど)の形式化です。

基本的に、2つの要素を持つセットの算術について話します。バイナリでカウントすることを考えてください。ブール代数は、この概念の起源であり、その理論的基盤です。Cのような言語の規則は、単純なアプリケーションです。


2
確かにできます。しかし、それを「標準」の方法に保つことは、一般的な算術(0 + 1 = 0ではなく0 + 1 = 1)にうまく適合します。
joshin4colours

2
はい。ただし、定義を逆にした場合は、おそらく+でANDと*でORを書くことになります。
ニールG

3
数学は最初に来ませんでした。Mathは、0と1がフィールドを形成することを認識しました。ANDは乗算のようなもので、ORは加算のようなものです。
カズ

1
@Kaz:しかし、{0、1}はORとANDでフィールドを形成しません。
ジョルジオ

2
それ以上の答えやコメントが言っているのは少し気になりますtrue = 1true != 0これはまったく同じではないため、まったく正確ではありません。のような比較を避けるべき理由の1つ(唯一ではない)if(something == true) { ... }
JensG

26

これは、電子機器からの「継承」とブール代数にも関係していると思いました。

  • 0= offnegativenofalse
  • 1= onpositiveyestrue

文字列が等しい場合、strcmpは0を返します。これは、実際には2つの文字列間の「距離」を計算するためです。0がfalseとみなされることも偶然です。

成功した場合に0を返すのは理にかなっています。この場合、0はエラーがないことを意味するために使用され、他の数値はエラーコードになるためです。成功のために他の番号を使用すると、成功コードは1つしかなく、複数のエラーコードを使用できるため、あまり意味がありません。「機能しましたか?」を使用します ifステートメント式と言う0 = yesの方が理にかなっていますが、式はより正確に「何か問題がありましたか?」そして、0 = noが非常に理にかなっていることがわかります。false/trueここで考えることは実際には意味がありませんno error code/error code


ハハ、リターンエラーの質問を明示的に述べる最初の人です。私はそれを私自身の方法で解釈し、他の方法で尋ねることができることをすでに知っていましたが、あなたはそれを明示的に表現する最初の人です(多くの答えとコメントのうち)。実際、私はどちらか一方の方法が意味をなさないとは言いませんが、両方とも異なる方法で意味をなします:)
モーウェン

1
実際に私が言うと思います0のためにsuccess/no error他の整数のエラーコードを表す際に理にかなっている唯一のものです。それは0また、表現するために起こるfalse);私たちはまったく真または偽ここでの話をされていないので、本当に重要ではありません。他のケースで
Svish

私は同じ考えを持っていたので、私は
アップした-user60812

1
あなたのポイントstrcmp()までの距離を計算することは非常に良いです。それは呼ばれていた場合はstrdiff()、その後if (!strdiff())非常に論理的だろう。
ケビンコックス14

「エレクトロニクス[...] 0 = [...]偽、1 = [...]真」-エレクトロニクスでも、これは単なる慣例であり、唯一ではありません。これを正の論理と呼びますが、負の論理を使用することもできます。正の電圧は偽を示し、負は真を示します。次に、ANDに使用する回路はORになり、ORはANDになります。ド・モーガンの法則により、すべてが同等になります。時には、便宜上、負論理で実装された電子回路の一部を見つけることがあります。その時点で、その部分の信号の名前はその上のバーで示されます。
ジュール

18

この記事で説明したように、値falsetrueは、整数0および1と混同しないでくださいが、2つの要素のガロア体(有限体)の要素で識別できます(こちらを参照)。

フィールドは、特定の公理を満たす2つの操作を持つセットです。

シンボル0と1は、実数も0と1のIDであるフィールド(有限ではない)でもあるため、フィールドの加法および乗法のIDを示すために通常使用されます。

加法的な恒等式は、すべてのxに対して次のようなフィールドの要素0です。

x + 0 = 0 + x = x

そして、乗法恒等式は、すべてのxに対して次のようなフィールドの要素1です。

x * 1 = 1 * x = x

2つの要素の有限体には、これらの2つの要素、つまり加法恒等式0(またはfalse)、および乗法恒等式1(またはtrue)のみがあります。このフィールドの2つの操作は、論理XOR(+)と論理AND(*)です。

注意。演算を反転する場合(XORは乗算で、ANDは加算)、乗算は加算に対して分散的ではなく、フィールドはもうありません。このような場合、2つの要素0と1を(任意の順序で)呼び出す理由はありません。また、XORの代わりにOR演算を選択できないことに注意してください。OR/ ANDを加算/乗算としてどのように解釈しても、結果の構造はフィールドではありません(フィールド公理で必要なすべての逆要素が存在するわけではありません)。

C関数について:

  • 多くの関数は、エラーコードである整数を返します。0はエラーなしを意味します。
  • 直感的に、この関数strcmpは2つの文字列の差を計算します。0は、2つの文字列に違いがない、つまり2つの文字列が等しいことを意味します。

上記の直感的な説明は、戻り値の解釈を思い出すのに役立ちますが、ライブラリのドキュメントを確認する方が簡単です。


1
これらを任意に交換すると、数学が機能しなくなることを示すために+1。
ジミーホファ

2
反転:2つの要素と演算*および+を持つフィールドを指定すると、Trueを0で識別し、Falseを1で識別します。ORを*で識別し、XORを+で識別します。
ニールG

1
これらの識別は両方とも同じフィールドで行われ、両方ともブール論理の規則と一致していることがわかります。あなたのメモは残念ながら間違っています:)
ニールG

1
True = 0で、XORが+であると仮定する場合、TrueはXORのIDでなければなりません。ただし、True XOR True = Falseであるためではありません。True XOR True = Trueになるように、操作XORをTrueで再定義しない限り。その後、もちろん名前を変更しただけなので、構築は機能します(数学的な構造では、常に名前の順列を作成して同型構造を取得できます)。そして、真のXOR真=偽と真を添加身元することはできません、彼らの通常の意味を持っている一方で、あなたはTRUE、FALSEとXORさせた場合、すなわち真は0にはできません
ジョルジオ

1
@Giorgio:前回のコメントのコメントごとに構造を修正しました…
ニールG

13

代替システムも設計上の決定として受け入れられることを考慮してください。

シェル:0終了ステータスはtrue、0以外はfalse

0終了ステータスをtrueとして処理するシェルの例は、すでに述べました。

$ ( exit 0 ) && echo "0 is true" || echo "0 is false"
0 is true
$ ( exit 1 ) && echo "1 is true" || echo "1 is false"
1 is false

理由は、成功する方法は1つですが、失敗する方法は多数あるため、「エラーなし」を意味する特別な値として0を使用することは実用的です。

Ruby:0は他の数字と同じです

「通常の」プログラミング言語の中には、Rubyなど、0を真の値として扱う異常値がいくつかあります。

$ irb
irb(main):001:0> 0 ? '0 is true' : '0 is false'
=> "0 is true"

根拠はそれだけですfalseし、nilfalseにする必要があります。多くのRuby初心者にとって、それは落とし穴です。ただし、場合によっては、0が他の数値と同様に扱われると便利です。

irb(main):002:0> (pos = 'axe' =~ /x/) ? "Found x at position #{pos}" : "x not found"
=> "Found x at position 1"
irb(main):003:0> (pos = 'xyz' =~ /x/) ? "Found x at position #{pos}" : "x not found"
=> "Found x at position 0"
irb(main):004:0> (pos = 'abc' =~ /x/) ? "Found x at position #{pos}" : "x not found"
=> "x not found"

ただし、このようなシステムは、ブール値を数値とは別のタイプとして区別できる言語でのみ機能します。コンピューティングの初期の時代には、アセンブリ言語や生の機械語を扱うプログラマーにはそのような贅沢はありませんでした。0を「空白」状態として扱い、コードが何かが発生したことをコードが検出したときにフラグとしてビットを1に設定することは、おそらく自然なことです。拡張により、慣例では、ゼロは偽として扱われ、ゼロ以外の値は真として扱われるようになりました。ただし、そのようにする必要はありません。

Java:数値をブール値として扱うことはできません

Javaでは、trueおよびfalseは唯一のブール値です。数値はブール値ではなく、ブール値にキャストすることさえできません(Java Language Specification、Sec 4.2.2):

整数型と型の間にはキャストがありませんboolean

このルールは、質問を完全に回避するだけです。ブール式はすべて、コードに明示的に記述する必要があります。


1
RebolとRedは両方とも0の値のINTEGERを扱います!値はtrueであり、別個のNONE!LOGIC!に加えて、条件付きfalseとして扱われるタイプ(NONEが1つの値のみ)偽。0をfalseとして扱うJavaScriptコードを作成しようとすると、かなりのフラストレーションを感じました。それは、動的に型付けされた言語の信じられないほど不格好な決定です。nullまたは0になる可能性のある何かをテストする場合if (thing === 0)は、書く必要がありますが、それはクールではありません。
HostileFork 14

@HostileFork知りません。動的言語で0true(他のすべての整数と同様に)意味があることがわかりました。Pythonで0キャッチしようとすると、ときどきa をキャッチNoneします。
モーウェン14

2
Rubyは異常値ではありません。RubyはこれをLispから取得します(Rubyはひそかに "MatzLisp"と呼ばれます)。Lispはコンピューターサイエンスの主流言語です。ゼロはテキストの一部であるため、POSIXシェルでは単なる真の値でもあります if [ 0 ] ; then echo this executes ; fi。偽のデータ値は空の文字列であり、テスト可能な偽りはコマンドの失敗した終了ステータスであり、ゼロで表されます。
カズ

8

一般的なケースに対処する前に、反例について議論することができます。

文字列の比較

実際には、多くの種類の比較についても同じことが言えます。このような比較により、2つのオブジェクト間の距離が計算されます。オブジェクトが等しい場合、距離は最小になります。したがって、「比較が成功した」場合、値は0です。しかし、実際には、戻り値はブール値でstrcmpなく、距離if (strcmp(...)) do_when_equal() else do_when_not_equal()です。

C ++では、0のときにtrueを返すようにオーバーライドstrcmpするDistanceオブジェクトを返すように再設計することができますoperator bool()(しかし、その後、別の一連の問題に噛まれます)。または、プレーンCには、streq文字列が等しい場合に1を返し、そうでない場合に0を返す関数のみがあります。

API呼び出し/プログラム終了コード

ここでは、何かがうまくいかなかった理由を気にします。これは、エラーが発生した場合に決定を下すためです。物事が成功すると、特に何も知りたくない-あなたの意図が実現されます。したがって、戻り値はこの情報を伝える必要があります。これはブール値ではなく、エラーコードです。特別なエラー値0は「エラーなし」を意味します。範囲の残りは、対処しなければならないローカルで意味のあるエラーを表します(1を含む、多くの場合、「不特定のエラー」を意味します)。

一般的なケース

これにより、なぜブール値でTrueあり、False一般にそれぞれ1と0で表されるのかという疑問が残ります。

さて、主観的な「この方が良い」という議論に加えて、ここにいくつかの理由があります(主観的)考えることができます:

  • 電気回路のアナロジー。電流は1秒間ON、0秒間OFFです。別のミックスではなく、(1、Yes、True、On)と(0、No、False、Off)を一緒にするのが好きです

  • メモリの初期化。Iときmemset(0)の変数の束は(int型、山車、boolsそれらも)私は彼らの値が最も保守的な仮定をマッチさせたいです。たとえば、私の合計は最初は0、述語はFalseなどです。

これらすべての理由は私の教育に関係しているのかもしれません-最初から0をTrueに関連付けるように教えられていたなら、私は反対に行きます。


2
実際、0をtrueとして扱うプログラミング言語が少なくとも1つあります。UNIXシェル。
ジャン・ヒューデック

実際の問題に対処するための+1:Morwennの質問のほとんどはまったく関係ありませんbool
dan04

@ dan04です。全体のポストは、から、キャストの選択の根拠についてですintbool多くのプログラミング言語インチ 比較とエラージェスチャの内容は、現在行われている方法とは別の方法でキャストするのが理にかなっている場所の例にすぎません。
モーウェン

6

高レベルの観点からは、3つのまったく異なるデータ型について話しています。

  1. ブール値。ブール代数の数学的慣習では、forに0、for falseに1 を使用するtrueので、その慣習に従うことは理にかなっています。この方法は直感的にも理にかなっていると思います。

  2. 比較の結果。これには3つの値があります:<=および>(それらのどれもでないことに注意してくださいtrue)。これらの場合、-1、0、および1の値(または、より一般的には、負の値、ゼロ、および正の値)を使用するのが理にかなっています。

    同等性を確認したいが、一般的な比較を実行する関数しかない場合、のようなものを使用して明示的にする必要があると思いますstrcmp(str1, str2) == 0!ブール値ではない値をブール値として処理するため、この状況での使用は混乱を招きます。

    また、比較と平等は同じものである必要はありません。たとえば、生年月日で人を注文した場合、Compare(me, myTwin)を返す必要0Equals(me, myTwin)ありfalseますが、を返す必要があります。

  3. 機能の成功または失敗、場合によってはその成功または失敗に関する詳細も含む。Windowsについて話している場合、このタイプが呼び出されHRESULT、ゼロ以外の値が必ずしも失敗を示すとは限りません。実際、負の値は失敗および非負の成功を示します。成功値は非常に頻繁S_OK = 0にありますが、たとえばS_FALSE = 1、または他の値にすることもできます。

混乱は、3つの論理的にまったく異なるデータ型が実際にはCおよびその他の言語で単一のデータ型(整数)として表され、条件で整数を使用できるという事実から生じます。しかし、ブール値を再定義して条件で単純な非ブール型を使用するのが簡単になるとは思わない。

また、Cの条件でよく使用される別のタイプ、つまりポインターを検討してください。そこNULLでは、- ポインター(として表される0)をとして扱うのが自然falseです。したがって、あなたの提案に従うことは、ポインターでの作業をより難しくします。(個人的には、ポインタをNULLブール値として扱うのではなく、明示的にポインタと比較することを好みます。)


4

ほとんどのCPUには、分岐に使用できるZEROフラグがあるため、ゼロはfalseになる可能性があります。比較操作を保存します。

理由を見てみましょう。

聴衆はおそらくアセンブリを読まないので、いくつかの擬似コード

c-ソースシンプルループはwibbleを10回呼び出します

for (int foo =10; foo>0; foo-- ) /* down count loop is shorter */
{  
   wibble();
}

そのためのいくつかのふりアセンブリ

0x1000 ld a 0x0a      'foo=10
0x1002 call 0x1234    'call wibble()
0x1005 dec a          'foo--
0x1006 jrnz -0x06      'jump back to 0x1000 if not zero
0x1008  

c-別の単純なループがwibbleを10回呼び出します

for (int foo =0; foo<10; foo-- ) /* up count loop is longer  */
{  
   wibble();
}

この場合のアセンブリのふり

0x1000 ld a 0x00      'foo=0
0x1002 call 0x1234    'call wibble()
0x1005 dec a          'foo--
0x1006 cmp 0x0a       'compare foo to 10 ( like a subtract but we throw the result away)
0x1008 jrns -0x08      'jump back to 0x1000 if compare was negative
0x100a  

いくつかのCソース

int foo=10;
if ( foo ) wibble()

そしてアセンブリ

0x1000 ld a 0x10
0x1002 jz 0x3
0x1004 call 0x1234
0x1007  

それがどれくらい短いか見てください?

いくつかのCソース

int foo=10;
if ( foo==0 ) wibble()

およびアセンブリ(比較なしで== 0を置き換えることができる、わずかにスマートなコンパイラを想定します)

0x1000 ld a 0x10
0x1002 jz 0x3
0x1004 call 0x1234
0x1007  

true = 1の規則を試してみましょう

いくつかのcソース#define TRUE 1 int foo = TRUE; if(foo == TRUE)wibble()

そしてアセンブリ

0x1000 ld a 0x1
0x1002 cmp a 0x01
0x1004 jz 0x3
0x1006 call 0x1234
0x1009 

ゼロ以外のtrueのケースがどれくらい短いかを見てください。

本当に初期のCPUには、アキュムレータに接続された小さなフラグのセットがありました。

a> bまたはa = bかどうかを確認するには、通常、比較命令を使用します。

  • Bがゼロでない場合-ゼロフラグが設定されている場合-単純な論理NORまたはアキュムレータのすべてのビットとして実装されます。
  • または、「符号ビット」、つまり2の補数演算を使用している場合はアキュムレータの最上位ビットを使用するNEGATIVE。(ほとんどの場合)

これを再度説明しましょう。一部の古いCPUでは、ゼロに等しいアキュムレーターまたはゼロより小さいアキュムレーターに比較命令を使用する必要はありませんでした。

ゼロが偽である理由がわかりましたか?

これは擬似コードであり、実際の命令セットはこのようには見えません。アセンブリを知っているなら、私はここで物事をかなり単純化していることを知っています。コンパイラー設計について何か知っていれば、この答えを読む必要はありません。ループの展開または分岐予測について何かを知っている人は誰でも、上級クラスは部屋203のホールにいます。


2
あなたのポイントはよくあるため、一つのことのためにここで行われていないif (foo)if (foo != 0)同じコードを生成する必要があり、そして第二に、あなたが実際に使用しているアセンブリ言語は、明示的なブールオペランドと、それらのテストを持っていることを示しています。たとえばをjz意味しjump if zeroます。言い換えればif (a == 0) goto target;。また、数量は直接テストされていません。条件は、特別なマシンワードに保存されるブールフラグに変換されます。これは、実際にはより多くのようなものだcpu.flags.zero = (a == 0); if (cpu.flags.zero) goto target;
カズ

いいえ、カズ、古いCPUはそのようには動作しませんでした。jz / jnzは、比較命令を実行せずに実行できます。これは私の投稿全体のポイントのようなものでした。
ティムウィリスクロフト

2
比較命令については何も書いていません。
カズ

jz命令はあるが、ないプロセッサを引用できますjnzか?(または条件付き命令のその他の非対称セット)
トビースペイト

3

1とtrueの間の対応は、数学的な性質によって必要とされることを示唆する多くの答えがあります。私はそのような財産を見つけることができず、それが純粋に歴史的な慣習であることを示唆しています。

2つの要素を持つフィールドを考えると、加算と乗算の2つの演算があります。このフィールドのブール演算は、次の2つの方法でマッピングできます。

伝統的に、Trueは1、Falseは0で識別します。ANDは*で識別し、XORは+で識別します。したがって、ORは飽和加算です。

ただし、Trueを0で、Falseを1で簡単に識別できます。次に、ORを*で、XNORを+で識別します。したがって、ANDは飽和加算です。


4
Wikipediaのリンクをたどっていたら、2つの要素のガロア体(en.wikipedia.org/wiki/GF%282%29)の概念に関連してブール代数の概念が閉じていることがわかりました。実数でも、その識別番号0と1であるフィールドであるため、シンボル0及び1は、従来、それぞれ、添加剤及び乗法アイデンティティを示すために使用されている
ジョルジョは、

1
@NeilGジョルジオは単なる大会以上のことを言おうとしていると思います。ブール代数の0と1は、GF(2)の0と1と基本的に同じです。GF(2)は、加算と乗算に関して、実数の0と1とほぼ同じ動作をします。
svick

1
@svick:いいえ、単純に乗算と飽和加算の名前をORとANDに変更し、ラベルを反転して0がTrue、1がFalseになるためです。ジョルジオは、それがコンピューターサイエンスの慣習として採用されたブール論理の慣習であると言っています。
ニールG

1
@Neil G:いいえ、フィールドは加算と乗算の分配性を必要とするため(en.wikipedia.org/wiki/Field_%28mathematics%29を参照)、+と*および0と1を反転できませんが、+:= ANDを設定するとおよび*:= XOR、T XOR(T AND F)= T XOR F = T、(T XOR T)AND(T XOR F)= F AND T = Fを取得します。したがって、操作とIDを反転することにより、フィールドはもうありません。したがって、適切なフィールドのIDとして0と1を定義するIMOは、偽りと真実をかなり忠実に捉えているようです。
ジョルジオ

1
@giorgio:答えを編集して、何が起こっているのかを明確にしました。
ニールG

3

奇妙なことに、ゼロは常に偽とは限りません。

特に、UnixおよびPosixの規則ではEXIT_SUCCESS、0(およびEXIT_FAILURE1)として定義されます。実際、それは標準的なCの規則ですらあります!

したがって、Posixシェルおよびexit(2)システムコールの場合、0は「成功」を意味し、直感的にはfalseよりも真実です。

特に、シェルifはプロセスの戻り値EXIT_SUCCESS(つまり0)が "then"ブランチに従うことを望んでいます!

Schemeでは(ただし、Common LispまたはMELTではない)0とnil(つまり()Schemeで)はtrueです。#f

同意します、私は厳選しています!


3

Cは、ハードウェアに近い低レベルプログラミングに使用されます。ハードウェアは、同じデータに対して、ビット演算と論理演算を切り替える必要がある場合があります。テストを実行するためだけに数値式をブール値に変換する必要があると、コードが煩雑になります。

次のように書くことができます:

if (modemctrl & MCTRL_CD) {
   /* carrier detect is on */
}

のではなく

if ((modemctrl & MCTRL_CD) != 0) {
    /* carrier detect is on */
}

1つの孤立した例ではそれほど悪くはありませんが、そうしなければならないのは面倒です。

同様に、逆の操作。比較などのブール演算の結果に対して、0または1を生成するのに便利です。modemctrlキャリア検出ビットがあるかどうかに基づいて、ある単語の3番目のビットを設定するとします。

flags |= ((modemctrl & MCTRL_CD) != 0) << 2;

ここでは、持っている必要があり!= 0biwiseの結果減らすために、&と表現し0たり1、しかし、結果はちょうど整数であるので、我々はさらに整数にブール値に変換するためにいくつかの迷惑なキャストを追加することから免れるされています。

現在のCにはbool型がありますが、それは良いことであり、そうでない場合に引き起こされる後方互換性による大規模な破損のために、このようなコードの妥当性を保持します。

Cが滑らかな別の例:4方向スイッチとして2つのブール条件をテストします。

switch (foo << 1 | bar) {  /* foo and bar booleans are 0 or 1 */
case 0: /* !foo && !bar */
   break;
case 1: /* !foo && bar */
   break;
case 2: /* foo && !bar */
   break;
case 3: /* foo && bar */
   break;
}

これをCプログラマから奪うことはできませんでした!

最後に、Cは一種の高水準アセンブリ言語として機能する場合があります。アセンブリ言語では、ブール型もありません。ブール値は、メモリ位置またはレジスタ内のビットまたはゼロとゼロ以外の値です。整数ゼロ、ブールゼロ、およびアドレスゼロはすべて、アセンブリ言語の命令セットで同じ方法でテストされます(おそらく浮動小数点ゼロでも)。Cとアセンブリ言語の類似性は便利です。たとえば、Cが別の言語(厳密に型付けされたブール値を持つ言語でも)をコンパイルするためのターゲット言語として使用される場合です。


0

ブール値または真理値には2つの値しかありません。真と偽。

これらは整数としてではなく、ビット(0および1)として表現する必要があります。

0または1以外の整数を偽と言っても偽ではありません。真理値表は、整数ではなく真理値を扱います。

将来の真理値から、-1または2はすべての真理値表とそれらに関連するブール論理を破ります。

  • 0および-1 ==?!
  • 0または2 ==?!

通常、ほとんどの言語にはboolean、整数などの数値型にキャストしたときにfalseが整数値0としてキャストされることが明らかになる型があります。


1
0 AND -1 ==キャストしたブール値。それが私の質問です。なぜ、TRUEまたはにキャストするのですかFALSE。私は決して言わなかった-たぶん私はしたが、それは意図していなかった-整数が真か偽か、ブールにキャストされたときにどちらに評価されるのかについて尋ねた。
モーウェン

-6

最終的に、いくつかのAPIは安っぽいので、あなたはコア言語を壊すことについて話しています。Crappy APIは新しいものではなく、言語を壊して修正することはできません。0はfalseで1はtrueであるという数学的事実であり、これを尊重しない言語は根本的に壊れています。3者間比較はニッチであり、bool3つの可能な結果を​​返すため、結果が暗黙的に変換されるビジネスはありません。古いC APIは単にひどいエラー処理を行うだけでなく、ひどいインターフェイスを持たないために必要な言語機能をCが持っていないため、大嫌いです。

暗黙的な整数->ブール変換を持たない言語については言っていないことに注意してください。


11
「0は偽で、1は真であるという数学的な事実です」Erm。
R.マルティーニョフェルナンデス

11
「0が偽で1が真であるという数学的な事実」の参照を引用できますか?あなたの答えは危険なほど暴言のように聞こえます。
ダンピチェルマン

14
それは数学的な事実ではありませんが、19世紀以来の数学的慣習です。
チャールズE.グラント

1
ブール代数は、0と1が加算と乗算に似た演算の単位元である有限体で表されます。これらの演算は、それぞれORとANDです。実際、ブール代数は並置がANDを+表し、記号がORを表す通常の代数とよく似ています。ですから、例えばをabc + a'b'c意味し(a and b and c) or (a and (not b) and (not c))ます。
カズ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.