Diese Frage mag dumm klingen, aber warum wird 0
zu false
und jeder andere [ganzzahlige] Wert für true
sind die meisten Programmiersprachen?
Zeichenfolgenvergleich
Da die Frage a zu sein scheint ein bisschen zu einfach, ich werde mich ein bisschen mehr erklären: Zunächst mag es jedem Programmierer offensichtlich erscheinen, aber warum sollte es keine Programmiersprache geben – es könnte tatsächlich eine geben, aber keine, die ich verwendet habe – wo 0
ergibt true
und alle anderen [ganzzahligen] Werte false
? Diese eine Bemerkung mag zufällig erscheinen, aber ich habe ein paar Beispiele, bei denen es eine gute Idee gewesen sein könnte. Nehmen wir zunächst das Beispiel eines Drei-Wege-Vergleichs von Zeichenfolgen. Ich nehme Cs strcmp
als Beispiel: Jeder Programmierer, der C als seine Muttersprache versucht, könnte versucht sein, den folgenden Code zu schreiben:
if (strcmp(str1, str2)) { // Do something... }
Da strcmp
0
zurückgibt Dies ergibt false
, wenn die Zeichenfolgen gleich sind. Was der anfängliche Programmierer versucht hat, schlägt kläglich fehl und er versteht im Allgemeinen zunächst nicht, warum. Hätte 0
stattdessen true
ausgewertet, hätte diese Funktion beim Vergleich auf Gleichheit in ihrem einfachsten Ausdruck – dem oben genannten – verwendet werden können. und die richtigen Überprüfungen für -1
und 1
wären nur bei Bedarf durchgeführt worden. Wir hätten den Rückgabetyp die meiste Zeit als bool
(in unseren Augen meine ich) betrachtet.
Lassen Sie uns außerdem einen neuen Typ sign
, das nur die Werte -1
, 0
und 1
. Das kann ziemlich praktisch sein. Stellen Sie sich vor, es gibt einen Raumschiffoperator in C ++ und wir möchten ihn für std::string
(nun, es gibt bereits die Funktion compare
, aber der Raumschiffoperator macht mehr Spaß). Die Deklaration wäre derzeit die folgende:
sign operator<=>(const std::string& lhs, const std::string& rhs);
Wurde 0
mit true
, der Raumschiffoperator würde nicht einmal existieren, und wir hätten operator==
folgendermaßen deklarieren können:
sign operator==(const std::string& lhs, const std::string& rhs);
Diese operator==
würde haben den Drei-Wege-Vergleich sofort durchgeführt und können weiterhin verwendet werden, um die folgende Überprüfung durchzuführen, während bei Bedarf weiterhin überprüft werden kann, welche Zeichenfolge der anderen lexikografisch überlegen ist:
if (str1 == str2) { // Do something... }
Behandlung alter Fehler
Wir haben jetzt Ausnahmen, daher gilt dieser Teil nur für die alten Sprachen, in denen dies nicht der Fall ist existieren (C zum Beispiel). Wenn wir uns die Standardbibliothek von C (und auch die von POSIX) ansehen, können wir sicher sehen, dass maaaaany-Funktionen bei Erfolg 0
und jede andere Ganzzahl zurückgeben. Ich habe leider einige Leute gesehen Gehen Sie folgendermaßen vor:
#define TRUE 0 // ... if (some_function() == TRUE) { // Here, TRUE would mean success... // Do something }
Wenn wir darüber nachdenken, wie wir denken Beim Programmieren haben wir oft das folgende Argumentationsmuster:
Do something Did it work? Yes -> That"s ok, one case to handle No -> Why? Many cases to handle
Wenn wir darüber nachdenken es wäre wieder sinnvoll gewesen, den einzigen neutralen Wert 0
auf yes
zu setzen (und so ist C “ Funktionen funktionieren), während alle anderen Werte vorhanden sein können, um die vielen Fälle von no
zu lösen. In allen mir bekannten Programmiersprachen (außer vielleicht einigen experimentellen esotherischen Sprachen) dass yes
in einer if
-Bedingung false
ergibt, wh Alle no
Fälle werden zu true
ausgewertet. Es gibt viele Situationen, in denen „es funktioniert“ einen Fall darstellt, während „es funktioniert nicht“ viele wahrscheinliche Ursachen darstellt. Wenn wir so denken, muss 0
true
und der Rest false
hätte viel mehr Sinn ergeben.
Schlussfolgerung
Meine Schlussfolgerung ist im Wesentlichen meine ursprüngliche Frage: Warum haben wir Sprachen entworfen, in denen 0
ist false
und die anderen Werte sind true
, unter Berücksichtigung meiner wenigen obigen Beispiele und vielleicht einiger weiterer, an die ich nicht gedacht habe?
Follow-up: Es ist schön zu sehen, dass es viele Antworten mit vielen Ideen und möglichst vielen möglichen Gründen gibt Ich liebe es, wie leidenschaftlich du darüber zu sein scheinst.Ich habe diese Frage ursprünglich aus Langeweile gestellt, aber da Sie so leidenschaftlich zu sein scheinen, habe ich mich entschlossen, ein wenig weiter zu gehen und nach zu fragen, welche Gründe hinter der booleschen Wahl für 0 und 1 stehen. a> auf Math.SE 🙂
Kommentare
-
strcmp()
ist kein gutes Beispiel für true oder false, da 3 verschiedene Werte zurückgegeben werden. Und Sie werden überrascht sein, wenn Sie eine Shell verwenden, bei der 0 wahr und alles andere falsch bedeutet. - @ ott–: In Unix-Shells bedeutet 0 Erfolg und nicht -zero bedeutet Fehler – nicht ganz dasselbe wie “ true “ und “ false „.
- @KeithThompson: In Bash (und anderen Shells) “ Erfolg “ und “ Fehler “ sind wirklich dieselben wie “ true “ und “ false „. Betrachten Sie beispielsweise die Anweisung
if true ; then ... ; fi
, wobeitrue
ein Befehl ist, der Null zurückgibt undif
zum Ausführen von...
. - In der Hardware gibt es keinerlei Boolesche Werte, nur Binärzahlen, und in den meisten historischen ISAs wird eine Zahl ungleich Null berücksichtigt als “ true “ in allen bedingten Verzweigungsanweisungen (es sei denn, sie ‚ verwenden Flags stattdessen). Daher sind die Low-Level-Sprachen auf jeden Fall verpflichtet, den zugrunde liegenden Hardwareeigenschaften zu folgen.
- @MasonWheeler Ein boolescher Typ ‚ bedeutet nichts. Zum Beispiel hat Python einen
bool
-Typ, aber Vergleiche / wenn Bedingungen usw. einen beliebigen Rückgabewert haben können.
Antwort
0
ist false
, da beide vorhanden sind Null Elemente gemeinsam semirings . Obwohl es sich um unterschiedliche Datentypen handelt, ist es intuitiv sinnvoll, zwischen ihnen zu konvertieren, da sie zu isomorphen algebraischen Strukturen gehören.
-
0
ist die Identität für die Addition und Null für die Multiplikation. Dies gilt für Ganzzahlen und Rationals, jedoch nicht für IEEE-754-Gleitkommazahlen:0.0 * NaN = NaN
und0.0 * Infinity = NaN
-
false
ist die Identität für Boolean xor (⊻) und Null für Boolean und (∧). Wenn Boolesche Werte als {0, 1} dargestellt werden – die Menge der Ganzzahlen Modulo 2 -, können Sie sich ⊻ als Addition ohne Übertrag und ∧ als Multiplikation vorstellen. -
""
und[]
sind Identitäten für die Verkettung, es gibt jedoch mehrere Operationen, für die sie als Null sinnvoll sind. Wiederholung ist eine, aber Wiederholung und Verkettung verteilen sich nicht, sodass diese Operationen kein Semiring bilden.
Solche impliziten Konvertierungen sind in kleinen Programmen hilfreich, aber in großen kann es schwieriger machen, über Programme nachzudenken. Nur einer der vielen Kompromisse beim Sprachdesign.
Kommentare
- Schön, dass Sie Listen erwähnt haben. (Übrigens ist
nil
sowohl die leere Liste[]
als auch der Wertfalse
in Common Lisp ; gibt es eine Tendenz, Identitäten aus verschiedenen Datentypen zusammenzuführen?) Sie müssen noch erklären, warum es natürlich ist, falsch als additive Identität und wahr als multiplikative Identität zu betrachten und nicht umgekehrt. Ist ‚ nicht möglich,true
als Identifikationsmerkmal fürAND
und Null fürOR
? - +1 für den Verweis auf ähnliche Identitäten. Schließlich eine Antwort, die nicht ‚ nicht nur auf die “ Konvention hinausläuft, sondern „.
- +1 für die Angabe von Details einer konkreten und sehr alten Mathematik, in der dies befolgt wurde und lange Sinn machte
- Diese Antwort ist nicht ‚ macht keinen Sinn.
true
ist auch die Identität und die Null von Semirings (Boolean und / oder). Es gibt keinen Grund, Appart Convention anzunehmen, dassfalse
näher an 0 liegt alstrue
. - @TonioElGringo: Der Unterschied zwischen wahr und falsch ist der Unterschied zwischen XOR und XNOR. Man kann isomorphe Ringe mit AND / XOR bilden, wobei wahr die multiplikative Identität und falsch die additive Identität ist, oder mit OR und XNOR, wobei falsch die multiplikative Identität und wahr die additive Identität ist, aber XNOR wird normalerweise nicht als häufig angesehen Grundlegende Operation wie XOR.
Antwort
Weil die Mathematik funktioniert.
FALSE OR TRUE is TRUE, because 0 | 1 is 1. ... insert many other examples here.
Traditionell haben C-Programme Bedingungen wie
if (someFunctionReturningANumber())
statt
if (someFunctionReturningANumber() != 0)
weil das Konzept, dass Null gleich falsch ist, gut verstanden ist.
Kommentare
- Die Sprachen sind so gestaltet, weil die Mathematik Sinn macht. Das war zuerst da.
- @Morwenn, es geht auf das 19. Jahrhundert und George Boole zurück. Die Leute haben False als 0 und True als! 0 länger dargestellt als es Computer gab.
- Ich ‚ verstehe nicht, warum die Mathematik nicht ‚ funktioniert nicht in die andere Richtung, wenn Sie lediglich alle Definitionen so ändern, dass AND + und OR * ist.
- Genau: Die Mathematik funktioniert in beide Richtungen und die Antwort auf Diese Frage scheint rein konventionell zu sein.
- @Robert ‚ wäre großartig, wenn Sie die “ mathematische Grundlagen “ in Ihrem Beitrag.
Antwort
Wie andere gesagt haben, stand die Mathematik an erster Stelle. Aus diesem Grund ist 0 false
und 1 true
.
Über welche Mathematik sprechen wir? Boolesche Algebren , die aus der Mitte des 19. Jahrhunderts stammen, lange bevor digitale Computer hinzukamen.
Man könnte auch sagen, dass die Konvention aus der Aussagenlogik stammt, die sogar älter als boolesche Algebren ist. Dies ist die Formalisierung vieler logischer Ergebnisse, die Programmierer kennen und lieben (false || x
entspricht x
, entspricht x
und so weiter).
Grundsätzlich sprechen wir über Arithmetik auf einer Menge mit zwei Elementen. Denken Sie darüber nach, binär zu zählen. Boolesche Algebren sind der Ursprung dieses Konzepts und seine theoretische Grundlage. Die Konventionen von Sprachen wie C sind nur eine einfache Anwendung.
Kommentare
- Sie könnten sicher. Aber die Beibehaltung des “ -Standards “ passt gut zur allgemeinen Arithmetik (0 + 1 = 1, nicht 0 +) 1 = 0).
- Ja, aber Sie würden vermutlich UND mit + und ODER mit * schreiben, wenn Sie auch die Definitionen umkehren würden.
- Die Mathematik hat nicht ‚ steht nicht an erster Stelle. Math hat erkannt, dass 0 und 1 ein Feld bilden, in dem AND wie Multiplikation und OR wie Addition ist.
- @ Kaz: Aber {0, 1} mit ODER und UND bildet kein Feld.
- Es stört mich ein wenig, dass mehr Antworten und Kommentare sagen, dass
true = 1
. Das ‚ ist nicht ganz genau, weiltrue != 0
nicht genau dasselbe ist. Ein Grund (nicht der einzige), warum Vergleiche wieif(something == true) { ... }
vermieden werden sollten.
Antwort
Ich dachte, das hat mit der „Vererbung“ von der Elektronik und auch der booleschen Algebra zu tun, wobei
-
0
=off
,negative
,no
,false
-
1
=on
,positive
,yes
,true
strcmp gibt 0 zurück, wenn die Zeichenfolgen gleich sind, was mit seiner Implementierung zu tun hat, da tatsächlich der „Abstand“ zwischen den beiden Zeichenfolgen berechnet wird. Dass 0 auch als falsch angesehen wird, ist nur ein Zufall.
0 bei Erfolg zurückzugeben, ist sinnvoll weil 0 in diesem Fall kein Fehler bedeutet und jede andere Zahl ein Fehlercode wäre. Die Verwendung einer anderen Zahl für den Erfolg wäre weniger sinnvoll, da Sie nur einen einzigen Erfolgscode haben, während Sie mehrere Fehlercodes haben können. Sie verwenden „Hat es funktioniert?“ als wenn der if-Anweisungsausdruck und sagen Sie 0 = yes sinnvoller wäre, aber der Ausdruck ist korrekter „Ist etwas schief gelaufen?“ und dann sehen Sie, dass 0 = nein sehr viel Sinn macht. An false/true
zu denken, ist hier nicht wirklich sinnvoll, da es tatsächlich no error code/error code
ist.
Kommentare
- Haha, Sie sind der erste, der die Rückgabefehlerfrage explizit angibt. Ich wusste bereits, dass ich es auf meine eigene Weise interpretierte und es könnte auch andersherum gefragt werden, aber Sie ‚ sind die Ersten, die es explizit ausdrücken (aus den vielen Antworten und Kommentaren).Eigentlich würde ich ‚ nicht sagen, dass der eine oder andere Weg keinen Sinn ergibt, sondern mehr, dass beide auf unterschiedliche Weise Sinn machen 🙂
- Eigentlich bin ich ‚ d say
0
fürsuccess/no error
ist das einzige, was Sinn macht, wenn andere Ganzzahlen Fehlercodes darstellen . Dass0
auchfalse
in anderen Fällen darstellt, spielt ‚ keine Rolle, da ‚ spricht hier überhaupt nicht über wahr oder falsch;) - Ich hatte die gleiche Idee, also habe ich
- Ihren Standpunkt erweitert
strcmp()
Die Berechnung der Entfernung ist ziemlich gut. Wenn esstrdiff()
genannt worden wäre, wäreif (!strdiff())
sehr logisch. - “ Elektronik […] wobei 0 = […] falsch, 1 = […] wahr “ – selbst in der Elektronik ist dies nur ein Konvention und ist nicht ‚ t die einzige. Wir nennen dies positive Logik, aber Sie können auch negative Logik verwenden, wobei eine positive Spannung falsch und eine negative wahr anzeigt. Dann wird die Schaltung, die Sie ‚ d für AND verwenden, zu OR, OR zu AND und so weiter. Aufgrund des Gesetzes von De Morgan ‚ ist alles gleichwertig. Manchmal finden Sie ‚ einen Teil einer elektronischen Schaltung, die der Einfachheit halber in negativer Logik implementiert ist. An diesem Punkt werden die Namen der Signale in diesem Teil mit einem Balken darüber gekennzeichnet.
Antwort
Wie in diesem Artikel erläutert Die Werte false
und true
sollten nicht mit den ganzen Zahlen 0 und 1 verwechselt werden, sondern können mit den Elementen des Galois-Feldes identifiziert werden (endliches Feld) zweier Elemente (siehe hier ).
Ein Feld ist eine Menge mit zwei Operationen, die bestimmte Axiome erfüllen.
Die Symbole 0 und 1 werden üblicherweise verwendet, um die additiven und multiplikativen Identitäten eines Feldes zu bezeichnen, da die reellen Zahlen auch ein Feld (aber kein endliches) sind, dessen Identitäten die Zahlen 0 und 1 sind.
Die additive Identität ist das Element 0 des Feldes, so dass für alle x:
x + 0 = 0 + x = x
und Die multiplikative Identität ist das Element 1 des Feldes, so dass für alle x:
x * 1 = 1 * x = x
Das endliche Feld zweier Elemente nur diese beiden Elemente enthält, nämlich das additive Identität 0 (oder false
) und die multiplikative Identität 1 (oder true
). Die beiden Operationen dieses Felds sind das logische XOR (+) und das logische UND (*).
Hinweis. Wenn Sie die Operationen umdrehen (XOR ist die Multiplikation und AND ist die Addition), ist die Multiplikation nicht über die Addition verteilt und Sie haben kein Feld mehr. In einem solchen Fall haben Sie keinen Grund, die beiden Elemente 0 und 1 (in beliebiger Reihenfolge) aufzurufen. Beachten Sie auch, dass Sie die Operation OR nicht anstelle von XOR auswählen können: Unabhängig davon, wie Sie OR / AND als Addition / Multiplikation interpretieren, ist die resultierende Struktur kein Feld (nicht alle inversen Elemente existieren gemäß den Feldaxiomen). P. >
Zu den C-Funktionen:
- Viele Funktionen geben eine Ganzzahl zurück, die ein Fehlercode ist. 0 bedeutet KEIN FEHLER.
- Intuitiv berechnet die Funktion
strcmp
die Differenz zwischen zwei Zeichenfolgen. 0 bedeutet, dass es keinen Unterschied zwischen zwei Zeichenfolgen gibt, dh dass zwei Zeichenfolgen gleich sind.
Die obigen intuitiven Erklärungen können helfen, sich an die Interpretation der Rückgabewerte zu erinnern, aber es ist noch einfacher Überprüfen Sie einfach die Bibliotheksdokumentation.
Kommentare
- +1, um zu zeigen, dass die Mathematik nicht mehr funktioniert, wenn Sie diese willkürlich austauschen.
- Umgedreht: Bei einem Feld mit zwei Elementen und Operationen * und + identifizieren wir True mit 0 und False mit 1. Wir identifizieren OR mit * und XOR mit +.
- Sie werden feststellen, dass beide Diese Identifikationen werden über dasselbe Feld durchgeführt und beide stimmen mit den Regeln der Booleschen Logik überein. Ihre Notiz ist leider falsch 🙂
- Wenn Sie annehmen, dass True = 0 und XOR + ist, muss True die Identität für XOR sein. Aber es liegt nicht daran, dass True XOR True = False ist. Es sei denn, Sie definieren die Operation XOR auf True neu, sodass True XOR True = True. Dann funktioniert Ihre Konstruktion natürlich, weil Sie gerade Dinge umbenannt haben (in jeder mathematischen Struktur können Sie immer erfolgreich eine Namenspermutation durchführen und eine isomorphe Struktur erhalten). Wenn Sie andererseits True, False und XOR ihre übliche Bedeutung haben lassen, kann True XOR True = False und True nicht die additive Identität sein, d. H. True kann nicht 0 sein.
- @Giorgio: Ich habe meine Konstruktion gemäß Ihrem Kommentar in meinem letzten Kommentar korrigiert …
Antwort
Sie sollten berücksichtigen, dass alternative Systeme auch akzeptable Entwurfsentscheidungen sein können.
Shells: 0-Exit-Status ist wahr, Nicht-Null ist falsch
Das Beispiel für Shells, die eine 0 behandeln Der Exit-Status als true wurde bereits erwähnt.
$ ( 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
Das Grundprinzip ist das Es gibt einen Weg zum Erfolg, aber viele Wege zum Scheitern. Daher ist es pragmatisch, 0 als Sonderwert für „keine Fehler“ zu verwenden.
Ruby: 0 ist wie jede andere Zahl
Unter „normalen“ Programmiersprachen gibt es einige Ausreißer wie Ruby, die 0 als wahren Wert behandeln.
$ irb irb(main):001:0> 0 ? "0 is true" : "0 is false" => "0 is true"
Die Begründung ist, dass nur false
und nil
falsch sein sollten. Für viele Ruby-Neulinge ist es „sa gotcha“. In einigen Fällen ist es jedoch schön, dass 0 wie jede andere Zahl behandelt wird.
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"
Allerdings Ein solches System funktioniert nur in einer Sprache, die Boolesche Werte als separaten Typ von Zahlen unterscheiden kann. In den früheren Tagen des Rechnens hatten Programmierer, die mit Assemblersprache oder roher Maschinensprache arbeiteten, keinen solchen Luxus. Es ist wahrscheinlich nur natürlich, 0 als „leeren“ Zustand zu behandeln und ein Bit als Flag auf 1 zu setzen, wenn der Code feststellt, dass etwas passiert ist. In der Erweiterung entwickelte sich die Konvention, dass Null als falsch behandelt wurde und Nicht-Null-Werte als wahr behandelt wurden. Dies muss jedoch nicht so sein.
Java: Zahlen können überhaupt nicht als Boolesche Werte behandelt werden.
In Java ist true
und false
sind die einzigen booleschen Werte. Zahlen sind keine booleschen Werte und können nicht einmal in boolesche Werte umgewandelt werden ( Java Language Specification, Sec 4.2.2 ):
Es gibt keine Umwandlungen zwischen Integraltypen und dem Typ
boolean
.
Diese Regel vermeidet nur die Frage insgesamt – alle booleschen Ausdrücke müssen explizit in den Code geschrieben werden.
Kommentare
- Rebol und Red behandeln beide 0-wertige INTEGER! -Werte als true und haben einen separaten NONE! -Typ (mit nur einem Wert, NONE) zusätzlich zu LOGIC! false als bedingt falsch behandelt. Ich ‚ habe erhebliche Frustration beim Versuch gefunden, JavaScript-Code zu schreiben, der 0 als falsch behandelt ein Inkr essbar klobige Entscheidung für eine dynamisch typisierte Sprache. Wenn Sie etwas testen möchten, das null oder 0 sein kann, müssen Sie am Ende
if (thing === 0)
schreiben, das ist einfach nicht cool. - @HostileFork I don ‚ weiß nicht. Ich finde es sinnvoll, dass
0
true
(wie jede andere Ganzzahl) in einer dynamischen Sprache ist. Ich habe manchmal eine0
abgefangen, als ich versucht habe,None
in Python abzufangen, und das kann manchmal ziemlich schwer zu erkennen sein. - Ruby ist kein Ausreißer. Ruby übernimmt dies von Lisp (Ruby wird sogar heimlich “ MatzLisp “ genannt). Lisp ist eine gängige Sprache in der Informatik. Null ist auch nur ein wahrer Wert in der POSIX-Shell, da es sich bei ‚ um einen Text handelt:
if [ 0 ] ; then echo this executes ; fi
. Der falsche Datenwert ist eine leere Zeichenfolge, und eine überprüfbare Falschheit ist ein fehlgeschlagener Beendigungsstatus eines Befehls, der durch eine nicht -Zull dargestellt wird.
Antwort
Bevor wir uns mit dem allgemeinen Fall befassen, können wir Ihre Gegenbeispiele diskutieren.
Zeichenfolgenvergleiche
Dasselbe gilt tatsächlich für viele Arten von Vergleichen. Solche Vergleiche berechnen einen Abstand zwischen zwei Objekten. Wenn die Objekte gleich sind, ist der Abstand minimal. Wenn der „Vergleich erfolgreich“ ist, ist der Wert 0. Tatsächlich ist der Rückgabewert von strcmp
kein Boolescher Wert, sondern ein Abstand, und Das, was unbewusste Programmierer einfängt, die if (strcmp(...)) do_when_equal() else do_when_not_equal()
ausführen.
In C ++ könnten wir strcmp
neu gestalten, um eine Distance
-Objekt, das operator bool()
überschreibt, um bei 0 true zurückzugeben (Sie würden dann jedoch von einer anderen Gruppe von Problemen gebissen). Oder in einfachem C haben Sie einfach eine streq
-Funktion, die 1 zurückgibt, wenn die Zeichenfolgen gleich sind, und andernfalls 0.
API-Aufrufe / Programm-Exit-Code
Hier ist Ihnen der Grund wichtig, warum ein Fehler aufgetreten ist, da dies die Fehlerentscheidungen in die Höhe treibt. Wenn die Dinge erfolgreich sind, möchten Sie nichts Besonderes wissen – Ihre Absicht wird verwirklicht. Der Rückgabewert muss daher diese Informationen vermitteln.Es ist kein Boolescher Wert, sondern ein Fehlercode. Der spezielle Fehlerwert 0 bedeutet „kein Fehler“. Der Rest des Bereichs stellt lokal bedeutsame Fehler dar, mit denen Sie sich befassen müssen (einschließlich 1, was häufig „nicht spezifizierter Fehler“ bedeutet).
Allgemeiner Fall
Dies lässt uns die Frage offen: Warum sind boolesche Werte True
und False
häufig mit 1 bzw. 0 dargestellt?
Nun, neben dem subjektiven Argument „es fühlt sich auf diese Weise besser an“ gibt es einige Gründe (auch subjektiv), an die ich denken kann:
-
Analogie der elektrischen Schaltung. Der Strom ist für 1s EIN und für 0s AUS. Ich mag es, (1, Ja, Richtig, Ein) zusammen und (0, Nein, Falsch, Aus) zusammen zu haben, anstatt eine andere Mischung
-
Speicherinitialisierungen. Wenn ich
memset(0)
eine Reihe von Variablen (seien es Ints, Floats, Bools), möchte ich, dass ihr Wert den konservativsten Annahmen entspricht. Z.B. Meine Summe ist anfänglich 0, das Prädikat ist False usw.
Vielleicht hängen all diese Gründe mit meiner Ausbildung zusammen – wenn mir beigebracht worden wäre, 0 mit True von der zu assoziieren Am Anfang würde ich umgekehrt vorgehen.
Kommentare
- Tatsächlich gibt es mindestens eine Programmiersprache, die 0 als wahr behandelt. Die Unix-Shell.
- +1 zur Behebung des eigentlichen Problems: Die meisten Fragen von Morwenn ‚ lauten nicht ‚ t über
bool
überhaupt. - @ dan04 Es ist. Der gesamte Beitrag befasst sich mit den Gründen für die Wahl der Besetzung von
int
bisbool
in vielen Programmiersprachen. Das Vergleichs- und Fehlergestationsmaterial ist nur ein Beispiel für Orte, an denen es sinnvoll gewesen wäre, es anders als das zu machen, das ‚ derzeit durchgeführt wird.
Antwort
Aus einer übergeordneten Perspektive sprechen Sie von drei ganz unterschiedlichen Datentypen:
-
Ein Boolescher Wert. Die mathematische Konvention in Boolesche Algebra lautet 0 für
false
und 1 fürtrue
, daher ist es sinnvoll, diese Konvention zu befolgen. Ich denke, dieser Weg ist auch intuitiv sinnvoller. -
Das Ergebnis des Vergleichs Drei Werte:
<
,=
und>
(beachten Sie, dass keiner von ihnentrue
). Für sie ist es sinnvoll, die Werte -1, 0 bzw. 1 (oder allgemeiner einen negativen Wert, Null und einen positiven Wert) zu verwenden.Wenn Sie auf Gleichheit prüfen möchten a Wenn Sie nur eine Funktion haben, die einen allgemeinen Vergleich durchführt, sollten Sie dies explizit machen, indem Sie etwas wie
strcmp(str1, str2) == 0
verwenden. Ich finde die Verwendung von!
in dieser Situation verwirrend, da ein nicht-boolescher Wert so behandelt wird, als wäre er ein boolescher Wert.Beachten Sie auch diesen Vergleich und Gleichheit muss nicht dasselbe sein. Wenn Sie beispielsweise Personen nach ihrem Geburtsdatum bestellen, sollte
Compare(me, myTwin)
0
zurückgeben , aberEquals(me, myTwin)
solltefalse
zurückgeben. -
Erfolg oder Misserfolg einer Funktion , möglicherweise auch mit Details zu diesem Erfolg oder Misserfolg. Wenn Sie über Windows sprechen, heißt dieser Typ
HRESULT
und ein Wert ungleich Null zeigen nicht unbedingt einen Fehler an. Tatsächlich zeigt ein negativer Wert einen Fehler und einen nicht negativen Erfolg an. Der Erfolgswert ist sehr oftS_OK = 0
, aber es kann auch beispielsweiseS_FALSE = 1
oder andere Werte sein.
Die Verwirrung ergibt sich aus der Tatsache diese drei logisch Ganz unterschiedliche Datentypen werden in C und einigen anderen Sprachen als einzelner Datentyp (eine Ganzzahl) dargestellt, und Sie können eine Ganzzahl in einer Bedingung verwenden. Ich halte es jedoch nicht für sinnvoll, Boolesche Werte neu zu definieren, um die Verwendung einiger nicht-Boolescher Typen unter Bedingungen zu vereinfachen.
Betrachten Sie auch einen anderen Typ, der häufig in einer Bedingung in C verwendet wird: einen Zeiger . Dort ist es natürlich, einen NULL
-Pointer (der als 0
dargestellt wird) als false
. Wenn Sie also Ihrem Vorschlag folgen, wird das Arbeiten mit Zeigern auch schwieriger. (Ich persönlich bevorzuge es jedoch, Zeiger explizit mit NULL
zu vergleichen, anstatt sie als Boolesche Werte zu behandeln.)
Antwort
Null kann falsch sein, da die meisten CPUs ein ZERO-Flag haben, das zum Verzweigen verwendet werden kann. Es speichert eine Vergleichsoperation.
Mal sehen warum.
Einige Pseudocodes, da das Publikum Assembler wahrscheinlich nicht liest.
Einfache Schleifenaufrufe mit c-Quelle werden 10 Mal wibble „> for (int foo =10; foo>0; foo-- ) /* down count loop is shorter */ { wibble(); }
eine vorgetäuschte Assembly für diese
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-Quelle eine andere einfache Schleifenaufrufe wibble 10 Mal
for (int foo =0; foo<10; foo-- ) /* up count loop is longer */ { wibble(); }
einige vorgetäuschte Assembly für diesen Fall
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
einige weitere c-Quellen
int foo=10; if ( foo ) wibble()
und die Assembly
0x1000 ld a 0x10 0x1002 jz 0x3 0x1004 call 0x1234 0x1007
sehen, wie kurz das ist?
weitere c-Quelle
int foo=10; if ( foo==0 ) wibble()
und die Assembly (nehmen wir einen geringfügig intelligenten Compiler an, der == 0 ohne Vergleich ersetzen kann )
0x1000 ld a 0x10 0x1002 jz 0x3 0x1004 call 0x1234 0x1007
Versuchen wir nun eine Konvention von true = 1
eine weitere c-Quelle #define TRUE 1 int foo = TRUE; if (foo == TRUE) wibble ()
und die Assembly
0x1000 ld a 0x1 0x1002 cmp a 0x01 0x1004 jz 0x3 0x1006 call 0x1234 0x1009
sehen, wie kurz der Fall mit true ungleich Null ist?
Wirklich Frühe CPUs hatten kleine Sätze von Flags an den Akkumulator angehängt.
Um zu überprüfen, ob a> b oder a = b im Allgemeinen eine Vergleichsanweisung benötigt.
- Es sei denn, B ist entweder NULL – in diesem Fall wird das ZERO-Flag gesetzt. Implementiert als einfaches logisches NOR oder alle Bits im Akkumulator.
- oder NEGATIV, bei dem nur das „Vorzeichenbit“ verwendet wird, dh das höchstwertige Bit des Akkumulators wenn Sie zwei Komplementarithmetik verwenden. (Meistens tun wir das)
Lassen Sie uns dies wiederholen. Bei einigen älteren CPUs mussten Sie keine Vergleichsanweisung für einen Akkumulator verwenden, der gleich NULL ist, oder für einen Akkumulator kleiner als Null.
Sehen Sie nun, warum Null möglicherweise falsch ist?
Bitte beachten Sie, dass dies Pseudo-Code ist und kein wirklicher Befehlssatz so aussieht. Wenn Sie die Montage kennen, wissen Sie, dass ich die Dinge hier sehr vereinfache. Wenn Sie etwas über das Compiler-Design wissen, mussten Sie diese Antwort nicht lesen. Jeder, der etwas über das Abrollen von Schleifen oder die Vorhersage von Zweigen weiß, ist in Raum 203 im Flur.
Kommentare
- Ihr Standpunkt ist hier nicht gut gemacht, weil zum einen
if (foo)
undif (foo != 0)
sollte denselben Code generieren, und zweitens ‚ zeigt, dass die Assemblersprache, die Sie ‚ verwenden, tatsächlich explizit ist Boolesche Operanden und Tests für sie. Zum Beispiel bedeutetjz
jump if zero
. Mit anderen Wortenif (a == 0) goto target;
Und die Menge wird nicht einmal direkt getestet; die Bedingung wird in ein boolesches Flag umgewandelt, das in einem speziellen Maschinenwort gespeichert ist. ‚ ähnelt eigentlich ehercpu.flags.zero = (a == 0); if (cpu.flags.zero) goto target;
- Nein Kaz, die ältere CPU ‚ hat so nicht funktioniert. T. Das jz / jnz kann ohne Vergleichsanweisung ausgeführt werden. Das war wirklich der Sinn meines gesamten Beitrags.
- Ich habe ‚ nichts über eine Vergleichsanweisung geschrieben.
- Können Sie einen Prozessor zitieren, der eine
jz
Anweisung, aber keinejnz
hat? (oder ein anderer asymmetrischer Satz von bedingten Anweisungen)
Antwort
Es gibt viele Antworten, die darauf hindeuten Die Entsprechung zwischen 1 und true ist aufgrund einer mathematischen Eigenschaft erforderlich. Ich kann keine solche Eigenschaft finden und vorschlagen, dass es sich um eine rein historische Konvention handelt.
Bei einem Feld mit zwei Elementen haben wir zwei Operationen: Addition und Multiplikation. Wir können Boolesche Operationen auf dieses Feld auf zwei Arten abbilden :
Traditionell identifizieren wir True mit 1 und False mit 0. Wir identifizieren AND mit * und XOR mit +. Somit ist OR eine sättigende Addition.
Wir könnten dies jedoch genauso leicht tun identifiziere True mit 0 und False mit 1. Dann identifizieren wir OR mit * und XNOR mit +. Somit sättigt AND die Addition.
Kommentare
- If Sie waren dem Link auf Wikipedia gefolgt. Sie hätten feststellen können, dass das Konzept einer booleschen Algebra geschlossen ist und mit dem eines Galois-Feldes aus zwei Elementen zusammenhängt ( en.wikipedia.org/wiki / GF% 282% 29 ). Die Symbole 0 und 1 werden üblicherweise verwendet, um die additiven bzw. multiplikativen Identitäten zu bezeichnen, da die reellen Zahlen auch ein Feld sind, dessen Identitäten die Zahlen 0 und 1 sind.
- @NeilG Ich denke, Giorgio versucht zu sagen, dass ‚ mehr als nur eine Konvention ist. 0 und 1 in der Booleschen Algebra sind im Grunde die gleichen wie 0 und 1 in GF (2), die sich in Bezug auf Addition und Multiplikation fast genauso wie 0 und 1 in reellen Zahlen verhalten.
- @svick: Nein , weil Sie Multiplikation und Sättigungsaddition einfach in ODER und UND umbenennen und dann die Beschriftungen umdrehen können, sodass 0 wahr und 1 falsch ist.Giorgio sagt, dass es eine Konvention der Booleschen Logik war, die als Konvention der Informatik übernommen wurde.
- @Neil G: Nein, Sie können + und * sowie 0 und 1 nicht umdrehen, da ein Feld Verteilungsfähigkeit erfordert der Multiplikation über Addition (siehe en.wikipedia.org/wiki/Field_%28mathematics%29 ), aber wenn Sie +: = AND und *: = XOR setzen Sie erhalten T XOR (T UND F) = T XOR F = T, während (T XOR T) UND (T XOR F) = F UND T = F. Durch Umdrehen der Operationen und Identitäten haben Sie daher kein Feld nicht mehr. Die IMO, die 0 und 1 als die Identität eines geeigneten Feldes definiert, scheint also ziemlich genau falsch und wahr zu erfassen.
- @giorgio: Ich habe die Antwort bearbeitet, um deutlich zu machen, was los ist.
Antwort
Seltsamerweise ist Null nicht immer falsch.
Insbesondere die Unix- und Posix-Konvention definiert EXIT_SUCCESS
als 0 (und EXIT_FAILURE
als 1). Tatsächlich ist es sogar eine Standardkonvention C !
Also für Posix-Shells und beenden (2) syscalls, 0 bedeutet „erfolgreich“, was intuitiv mehr wahr als falsch ist.
Insbesondere möchte die Shell „s if
a Prozessrückgabe EXIT_SUCCESS
(dh 0), um seinem „then“ -Zweig zu folgen!
Im Schema (jedoch nicht in Common Lisp oder in MELT ) 0 und nil (dh ()
im Schema) sind wahr, da der einzige falsche Wert #f
Ich stimme zu, ich wähle nicht!
Antwort
C wird für die Low-Level-Programmierung in der Nähe der Hardware verwendet, einem Bereich, in dem Sie manchmal zwischen bitweisen und logischen Operationen für dieselben Daten wechseln müssen. Wenn Sie einen numerischen Ausdruck nur zur Durchführung eines Tests in einen Booleschen Wert konvertieren müssen, ist dies unübersichtlich den Code.
Sie können Dinge schreiben wie:
if (modemctrl & MCTRL_CD) { /* carrier detect is on */ }
anstatt
if ((modemctrl & MCTRL_CD) != 0) { /* carrier detect is on */ }
In einem isolierten Beispiel ist es nicht so schlimm, aber das zu tun wird lästig.
Ebenso können Sie Operationen umkehren. Für das Ergebnis einer booleschen Operation wie eines Vergleichs ist es nützlich, nur eine 0 oder 1 zu erzeugen: Angenommen, wir möchten das dritte Bit eines Wortes basierend darauf setzen, ob modemctrl
hat das Trägererkennungsbit:
flags |= ((modemctrl & MCTRL_CD) != 0) << 2;
Hier müssen wir das != 0
, um das Ergebnis des biwise &
-Ausdrucks auf 0
oder , aber da das Ergebnis nur eine Ganzzahl ist, müssen wir keine nervige Umwandlung hinzufügen, um Boolesche Werte in Ganzzahlen weiter umzuwandeln.
Obwohl das moderne C jetzt ein bool
Typ, behält die Gültigkeit von Code wie diesem bei, sowohl weil es eine gute Sache ist, als auch wegen des massiven Bruches mit der Abwärtskompatibilität, der sonst verursacht würde.
Ein weiteres Beispiel, bei dem C glatt ist: Testen von zwei booleschen Bedingungen als Vier-Wege-Schalter:
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; }
Sie konnten dies dem C-Programmierer nicht kampflos wegnehmen!
Schließlich dient C manchmal als eine Art hochrangige Assemblersprache. In Assemblersprachen haben wir auch keine booleschen Typen. Ein boolescher Wert ist nur ein Bit oder eine Null gegenüber einem Wert ungleich Null in einem Speicherort oder Register. Eine ganzzahlige Null, eine boolesche Null und die Adresse Null werden alle auf dieselbe Weise in Assembler-Befehlssätzen (und möglicherweise sogar Gleitkomma-Null) getestet. Die Ähnlichkeit zwischen C und Assemblersprache ist nützlich, wenn beispielsweise C als Zielsprache zum Kompilieren einer anderen Sprache verwendet wird (auch einer, die stark boolesche Werte aufweist!).
Antwort
Ein Boolescher Wert oder Wahrheitswert hat nur 2 Werte. Richtig und falsch.
Diese sollten nicht als Ganzzahlen, sondern als Bits (0 und 1) dargestellt werden ).
Es ist eine verwirrende Aussage, zu sagen, dass eine andere Ganzzahl neben 0 oder 1 nicht falsch ist. Wahrheitstabellen befassen sich mit Wahrheitswerten, nicht mit ganzen Zahlen.
Aus der Perspektive eines Wahrheitswertes würden -1 oder 2 alle Wahrheitstabellen und jede damit verbundene boolesche Logik brechen.
- 0 UND -1 == ?!
- 0 ODER 2 == ?!
Die meisten Sprachen haben normalerweise eine boolean
Typ, der bei der Umwandlung in einen Zahlentyp wie eine Ganzzahl false als Ganzzahlwert von 0 anzeigt.
Kommentare
- 0 UND -1 == Welchen booleschen Wert Sie auch immer verwenden. Darum geht es bei ‚, warum sie in
TRUE
oderFALSE
umgewandelt werden.Ich habe nie gesagt – vielleicht habe ich es getan, aber es war nicht beabsichtigt -, dass ganze Zahlen wahr oder falsch sind. Ich habe gefragt, warum sie je nach Boolescher Wert ausgewertet werden.
Antwort
Letztendlich sprechen Sie davon, die Kernsprache zu brechen, weil einige APIs beschissen sind. Crappy APIs sind nicht neu, und Sie können sie nicht reparieren, indem Sie die Sprache brechen. Es ist eine mathematische Tatsache, dass 0 falsch und 1 wahr ist, und jede Sprache, die dies nicht respektiert, ist grundlegend kaputt. Der Drei-Wege-Vergleich ist Nische und hat nichts damit zu tun, dass das Ergebnis implizit in bool
konvertiert wird, da drei mögliche Ergebnisse zurückgegeben werden. Die alten C-APIs haben einfach eine schreckliche Fehlerbehandlung und sind auch behindert, weil C nicht über die erforderlichen Sprachfunktionen verfügt, um keine schrecklichen Schnittstellen zu haben.
Beachten Sie, dass ich dies nicht für Sprachen sage, die nicht implizit sind Ganzzahl-> Boolesche Konvertierung.
Kommentare
- “ Es ist eine mathematische Tatsache, dass 0 falsch ist und 1 ist wahr “ Ähm.
- Können Sie eine Referenz für Ihre “ mathematische Tatsache zitieren, dass 0 falsch ist und 1 ist wahr „? Ihre Antwort klingt gefährlich wie ein Schimpfen.
- ‚ ist keine mathematische Tatsache, aber ‚ Eine mathematische Konvention seit dem 19. Jahrhundert.
- Die Boolesche Algebra wird durch ein endliches Feld dargestellt, in dem 0 und 1 die Identitätselemente für Operationen sind, die Addition und Multiplikation ähneln. Diese Operationen sind jeweils ODER und UND. Tatsächlich wird die Boolesche Algebra ähnlich wie die normale Algebra geschrieben, wobei die Gegenüberstellung UND und das Symbol
+
OR bedeutet. So bedeutet beispielsweiseabc + a'b'c
(a and b and c) or (a and (not b) and (not c))
.