Pourquoi 0 est-il faux?

Cette question peut sembler stupide, mais pourquoi 0 est-il évalué à false et toute autre valeur [integer] à true est la plupart des langages de programmation?

Comparaison de chaînes

Puisque la question semble un peu trop simple, je vais mexpliquer un peu plus: tout dabord, cela peut sembler évident à nimporte quel programmeur, mais pourquoi ny aurait-il pas de langage de programmation – il y en a peut-être, mais pas celui que jai utilisé – où 0 est évalué à true et toutes les autres valeurs [integer] à false? Cette remarque peut sembler aléatoire, mais jai quelques exemples où cela a peut-être été une bonne idée. Tout dabord, prenons lexemple de la comparaison des chaînes à trois voies, je prendrai C « s strcmp par exemple: tout programmeur essayant le C comme premier langage peut être tenté décrire le code suivant:

Puisque strcmp renvoie 0 qui évalue à false lorsque les chaînes sont égales, ce que le programmeur débutant a essayé de faire échoue lamentablement et il ne comprend généralement pas pourquoi au début. Si 0 évalué à true à la place, cette fonction aurait pu être utilisée dans son expression la plus simple – celle ci-dessus – lors de la comparaison pour légalité, et les vérifications appropriées pour -1 et 1 nauraient été effectuées que lorsque cela était nécessaire. Nous aurions considéré le type de retour comme bool (dans notre esprit je veux dire) la plupart du temps.

De plus, introduisons un nouveau type, sign, qui prend juste les valeurs -1, 0 et 1. Cela peut être très pratique. Imaginez quil existe un opérateur de vaisseau spatial en C ++ et que nous le voulons pour std::string (enfin, il y a déjà la fonction compare, mais lopérateur du vaisseau spatial est plus amusant). La déclaration serait actuellement la suivante:

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

Est-ce que 0 a été évalué à true, lopérateur de vaisseau spatial nexisterait même pas et nous aurions pu déclarer operator== de cette façon:

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

Ce operator== ont géré la comparaison à trois à la fois, et pourraient encore être utilisés pour effectuer la vérification suivante tout en étant capable de vérifier quelle chaîne est lexicographiquement supérieure à lautre lorsque cela est nécessaire:

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

Gestion des anciennes erreurs

Nous avons maintenant des exceptions, donc cette partie ne sapplique quaux anciennes langues où rien de tel existent (C par exemple). Si nous regardons la bibliothèque standard de C (et celle de POSIX aussi), nous pouvons voir avec certitude que les fonctions maaaaany renvoient 0 en cas de succès et tout entier sinon. Jai malheureusement vu certaines personnes faites ce genre de choses:

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

Si nous réfléchissons à notre façon de penser programmation, nous avons souvent le modèle de raisonnement suivant:

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

Si nous pensons à là encore, il aurait été logique de mettre la seule valeur neutre, 0, à yes (et cest « s comment C » s fonctions fonctionnent), alors que toutes les autres valeurs peuvent être là pour résoudre les nombreux cas de no. Cependant, dans tous les langages de programmation que je connais (sauf peut-être quelques langages esotheriques expérimentaux), que yes évalue à false dans une condition if, wh ilez tous les cas no évalués à true. Il existe de nombreuses situations où «cela fonctionne» représente un cas tandis que «cela ne fonctionne pas» représente de nombreuses causes probables. Si nous y pensons de cette façon, avoir 0 évalué à true et le reste à false aurait eu beaucoup plus de sens.

Conclusion

Ma conclusion est essentiellement ma question initiale: pourquoi avons-nous conçu des langages où 0 est false et les autres valeurs sont true, en tenant compte de mes quelques exemples ci-dessus et peut-être dautres auxquels je nai pas pensé?

Suivi: Cest agréable de voir quil y a beaucoup de réponses avec beaucoup didées et autant de raisons possibles pour que ce soit comme ça. Jadore à quel point tu sembles être passionné à ce sujet.Jai initialement posé cette question par ennui, mais comme vous semblez si passionné, jai décidé daller un peu plus loin et de poser des questions sur la raison dêtre du choix booléen pour 0 et 1 sur Math.SE 🙂

Commentaires

  • strcmp() nest pas un bon exemple pour true ou false, car il renvoie 3 valeurs différentes. Et vous serez surpris lorsque vous commencerez à utiliser un shell, où 0 signifie vrai et tout le reste signifie faux.
  • @ ott–: Dans les shells Unix, 0 signifie succès et non -zéro signifie échec – pas tout à fait la même chose que  » true  » et  » false « .
  • @KeithThompson: Dans Bash (et dautres shells),  » succès  » et  » échec  » sont vraiment les mêmes que  » true  » et  » false « . Prenons, par exemple, linstruction if true ; then ... ; fi, où true est une commande qui renvoie zéro et indique if pour exécuter ....
  • Il ny a aucun booléen dans le matériel, uniquement des nombres binaires, et dans la plupart des ISA historiques, un nombre différent de zéro est considéré comme  » true  » dans toutes les instructions de branchement conditionnel (sauf si elles ‘ utilisent des indicateurs au lieu). Ainsi, les langages de bas niveau sont obligés de suivre les propriétés matérielles sous-jacentes.
  • @MasonWheeler Avoir un type booléen nimplique rien ‘. Par exemple, python a un type bool mais les comparaisons / si les conditions etc. peuvent avoir nimporte quelle valeur de retour.

Réponse

0 est false car ils sont tous les deux zéro élément dans les semirings communs. Même sil sagit de types de données distincts, il est intuitif de les convertir car ils appartiennent à des structures algébriques isomorphes.

  • 0 est lidentité pour laddition et zéro pour la multiplication. Ceci est vrai pour les entiers et les rationnels, mais pas les nombres à virgule flottante IEEE-754: 0.0 * NaN = NaN et 0.0 * Infinity = NaN .

  • false est lidentité pour le booléen xor (⊻) et zéro pour le booléen et (∧). Si les booléens sont représentés par {0, 1} – lensemble des entiers modulo 2 – vous pouvez considérer ⊻ comme une addition sans report et ∧ comme une multiplication.

  • "" et [] sont des identités pour la concaténation, mais il existe plusieurs opérations pour lesquelles elles ont un sens comme zéro. La répétition en est une, mais la répétition et la concaténation ne se distribuent pas, donc ces opérations ne forment pas un semiring.

De telles conversions implicites sont utiles dans les petits programmes, mais dans les grands peut rendre les programmes plus difficiles à raisonner. Juste un des nombreux compromis dans la conception du langage.

Commentaires

  • Bien que vous ayez mentionné les listes. (BTW, nil est à la fois la liste vide [] et la valeur false en Common Lisp ; y a-t-il une tendance à fusionner les identités de différents types de données?) Vous devez encore expliquer pourquoi il est naturel de considérer le faux comme une identité additive et le vrai comme une identité multiplicative et non linverse. Nest-il pas ‘ possible de considérer true comme identifiant pour AND et zéro pour OR?
  • +1 pour faire référence à des identités similaires. Enfin une réponse qui ‘ t se résume simplement à la  » convention, la traiter « .
  • +1 pour donner des détails sur un calcul concret et très ancien dans lequel cela a été suivi et fait sens depuis longtemps
  • Cette réponse ne ‘ t a du sens. true est aussi lidentité et le zéro des semirings (booléen et / ou). Il ny a aucune raison, selon la convention, de considérer que false est plus proche de 0 que true.
  • @TonioElGringo: La différence entre vrai et faux est la différence entre XOR et XNOR. On peut former des anneaux isomorphes en utilisant AND / XOR, où true est lidentité multiplicative et false ladditif, ou avec OR et XNOR, où false est lidentité multiplicative et true est ladditif, mais XNOR nest généralement pas considéré comme commun opération fondamentale comme XOR.

Réponse

Parce que les maths fonctionnent.

FALSE OR TRUE is TRUE, because 0 | 1 is 1. ... insert many other examples here. 

Traditionnellement, les programmes C ont des conditions telles que

 if (someFunctionReturningANumber())  

plutôt que

 if (someFunctionReturningANumber() != 0)  

car le concept de zéro équivalent à faux est bien compris.

Commentaires

  • Les langages sont conçus comme ça parce que les mathématiques ont du sens. Cela est venu en premier.
  • @Morwenn, cela remonte au 19ème siècle et à George Boole. Les gens représentent False comme 0 et True comme! 0 depuis plus longtemps quil ny a eu dordinateurs.
  • Je ne ‘ pas voir pourquoi le calcul ne ‘ t fonctionner dans lautre sens si vous changez simplement toutes les définitions pour que AND soit + et OR soit *.
  • Exactement: le calcul fonctionne dans les deux sens et la réponse à cette question semble être purement conventionnelle.
  • @Robert Cela ‘ serait génial si vous pouviez épeler le  » fondements mathématiques  » dans votre message.

Réponse

Comme d’autres l’ont dit, les calculs sont venus en premier. Cest pourquoi 0 est false et 1 est true.

De quels mathématiques parlons-nous? Algèbres booléennes qui datent du milieu des années 1800, bien avant larrivée des ordinateurs numériques.

On pourrait aussi dire que la convention est issue de la logique propositionnelle , qui est encore plus ancienne que les algèbres booléennes. Il sagit de la formalisation de nombreux résultats logiques que les programmeurs connaissent et apprécient (false || x equals x, true && x est égal à x et ainsi de suite).

Fondamentalement, nous parlons darithmétique sur un ensemble à deux éléments. Pensez à compter en binaire. Les algèbres booléennes sont à lorigine de ce concept et de son fondement théorique. Les conventions des langages comme C ne sont quune simple application.

Commentaires

  • Vous pourriez , bien sûr. Mais en gardant la méthode  » standard « , elle sintègre bien avec larithmétique générale (0 + 1 = 1, pas 0 + 1 = 0).
  • Oui, mais vous écririez probablement AND avec + et OR avec * si vous inversiez également les définitions.
  • Le calcul na pas ‘ t vient en premier. Math a reconnu que 0 et 1 forment un champ, dans lequel AND est comme la multiplication et OR est comme laddition.
  • @ Kaz: Mais {0, 1} avec OR et AND ne forme pas un champ.
  • Cela me dérange un peu que plus de réponses et de commentaires disent que true = 1. Ce ‘ nest pas tout à fait exact, car true != 0 ce nest pas exactement la même chose. Une raison (pas la seule) pour laquelle il faut éviter les comparaisons comme if(something == true) { ... }.

Réponse

Je pensais que cela avait à voir avec « lhéritage » de lélectronique, et aussi lalgèbre booléenne, où

  • 0 = off, negative, no, false
  • 1 = on, positive, yes, true

strcmp renvoie 0 lorsque les chaînes sont égales a à voir avec son implémentation, car ce quil fait réellement est de calculer la « distance » entre les deux chaînes. Le fait que 0 soit également considéré comme faux nest quune coïncidence.

renvoyer 0 en cas de succès est logique car 0 dans ce cas est utilisé pour signifier aucune erreur et tout autre nombre serait un code derreur. Lutilisation de tout autre numéro pour réussir aurait moins de sens puisque vous navez quun seul code de réussite, alors que vous pouvez avoir plusieurs codes derreur. Vous utilisez « Cela a-t-il fonctionné? » comme lexpression de linstruction if et dire 0 = yes aurait plus de sens, mais lexpression est plus correctement « Quelque chose sest mal passé? » et puis vous voyez que 0 = non a beaucoup de sens. Penser à false/true na pas vraiment de sens ici, car cest en fait no error code/error code.

Commentaires

  • Haha, vous êtes le premier à énoncer explicitement la question derreur de retour. Je savais déjà que je linterprétais à ma manière et cela pouvait être demandé dans lautre sens, mais vous ‘ êtes le premier à lexprimer explicitement (parmi les nombreuses réponses et commentaires).En fait, je ne dirais pas ‘ que lune ou lautre manière na aucun sens, mais plus que les deux ont un sens de différentes manières 🙂
  • En fait, je ‘ d say 0 for success/no error est la seule chose qui a du sens lorsque dautres entiers représentent des codes derreur . Cela 0 se trouve également représenter false dans dautres cas na ‘ t vraiment dimportance, puisque nous ne parlons ‘ du tout de vrai ou de faux ici;)
  • Jai eu la même idée donc jai augmenté
  • Votre point sur strcmp() calculer la distance est assez bon. Sil avait été appelé strdiff() alors if (!strdiff()) serait très logique.
  •  » électronique […] où 0 = […] faux, 1 = […] vrai  » – même en électronique, ce nest quun convention , et nest ‘ t la seule. Nous appelons cette logique positive, mais vous pouvez également utiliser la logique négative, où une tension positive indique faux et négatif indique vrai. Ensuite, le circuit que vous utilisez ‘ pour AND devient OR, OR devient AND, et ainsi de suite. En raison de la loi de De Morgan ‘, tout finit par être équivalent. Parfois, vous trouverez ‘ une partie dun circuit électronique implémenté en logique négative pour plus de commodité, auquel cas les noms des signaux de cette partie sont notés avec une barre au-dessus deux.

Réponse

Comme expliqué dans cet article , les valeurs false et true ne doivent pas être confondues avec les entiers 0 et 1, mais peuvent être identifiées avec les éléments du champ de Galois (corps fini) de deux éléments (voir ici ).

Un champ est un ensemble avec deux opérations qui satisfont certains axiomes.

Les symboles 0 et 1 sont classiquement utilisés pour désigner les identités additive et multiplicative dun champ car les nombres réels sont aussi un champ (mais pas fini) dont les identités sont les nombres 0 et 1.

Lidentité additive est lélément 0 du champ, tel que pour tout x:

x + 0 = 0 + x = x 

et lidentité multiplicative est lélément 1 du champ, tel que pour tout x:

x * 1 = 1 * x = x 

Le corps fini de deux éléments na que ces deux éléments, à savoir le identité additive 0 (ou false), et lidentité multiplicative 1 (ou true). Les deux opérations de ce champ sont le XOR logique (+) et le ET logique (*).

Remarque. Si vous retournez les opérations (XOR est la multiplication et AND est laddition) alors la multiplication nest pas distributive sur laddition et vous navez plus de champ. Dans un tel cas, vous navez aucune raison dappeler les deux éléments 0 et 1 (dans nimporte quel ordre). Notez également que vous ne pouvez pas choisir lopération OR au lieu de XOR: peu importe comment vous interprétez OR / AND comme addition / multiplication, la structure résultante nest pas un champ (tous les éléments inverses nexistent pas comme lexigent les axiomes de champ).

Concernant les fonctions C:

  • De nombreuses fonctions renvoient un entier qui est un code derreur. 0 signifie PAS DERREUR.
  • Intuitivement, la fonction strcmp calcule la différence entre deux chaînes. 0 signifie quil ny a pas de différence entre deux chaînes, cest-à-dire que deux chaînes sont égales.

Les explications intuitives ci-dessus peuvent aider à se souvenir de linterprétation des valeurs de retour, mais il est encore plus facile de il suffit de consulter la documentation de la bibliothèque.

Commentaires

  • +1 pour montrer que si vous les échangez arbitrairement, les calculs ne fonctionnent plus.
  • Inversé: étant donné un champ avec deux éléments et des opérations * et +, nous identifions Vrai avec 0 et Faux avec 1. Nous identifions OU avec * et XOR avec +.
  • Vous constaterez que les deux de ces identifications se font sur le même champ et les deux sont cohérentes avec les règles de la logique booléenne. Votre note est malheureusement incorrecte 🙂
  • Si vous supposez que True = 0, et XOR est +, alors True doit être lidentité de XOR. Mais ce nest pas parce que True XOR True = False. Sauf si vous redéfinissez lopération XOR sur True pour que True XOR True = True. Ensuite, bien sûr, votre construction fonctionne parce que vous venez de renommer des choses (dans toute structure mathématique, vous pouvez toujours réussir à faire une permutation de nom et obtenir une structure isomorphe). Dautre part, si vous laissez True, False et XOR ont leur signification habituelle, alors True XOR True = False et True ne peut pas être lidentité additive, cest-à-dire que True ne peut pas être 0.
  • @Giorgio: Jai corrigé ma construction par votre commentaire dans mon dernier commentaire…

Réponse

Vous devez considérer que des systèmes alternatifs peuvent également être des décisions de conception acceptables.

Coques: létat de sortie 0 est vrai, non nul est faux

Lexemple des coques traitant un 0 létat de sortie true a déjà été mentionné.

 $ ( 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  

La raison en est que il y a une façon de réussir, mais de nombreuses façons déchouer, donc utiliser 0 comme valeur spéciale signifiant « pas derreur » est pragmatique.

Ruby: 0 est comme nimporte quel autre nombre

Parmi les langages de programmation « normaux », il existe des valeurs aberrantes, telles que Ruby, qui traitent 0 comme une valeur vraie.

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

Le la justification est que seuls false et nil doivent être faux. Pour de nombreux novices en Ruby, cest « un piège. Cependant, dans certains cas, cest bien que 0 soit traité comme nimporte quel autre nombre.

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" 

Cependant , un tel système ne fonctionne que dans une langue capable de distinguer les booléens comme un type distinct des nombres. Dans les premiers jours de linformatique, les programmeurs travaillant avec le langage dassemblage ou le langage machine brut navaient pas un tel luxe. Il est probablement tout simplement naturel de traiter 0 comme létat « vide » et de mettre un bit à 1 comme indicateur lorsque le code a détecté que quelque chose sest produit. Par extension, la convention sest développée selon laquelle zéro était traité comme faux et les valeurs non nulles ont fini par être traitées comme vraies. Cependant, il ne doit pas en être ainsi.

Java: les nombres ne peuvent pas du tout être traités comme des booléens

En Java, true et false sont les seules valeurs booléennes. Les nombres ne sont pas des booléens et ne peuvent même pas être convertis en booléens ( Spécification du langage Java, Sec 4.2.2 ):

Il ny a pas de casts entre les types intégraux et le type boolean .

Cette règle évite complètement la question – toutes les expressions booléennes doivent être explicitement écrites dans le code.

Commentaires

  • Rebol et Red traitent tous les deux les valeurs INTEGER! de valeur 0 comme true et ont un type AUCUN! distinct (avec une seule valeur, NONE) traité comme conditionnel false en plus de LOGIC! false. ‘ jai trouvé une frustration importante en essayant décrire du code JavaScript qui traite 0 comme faux; cest un incr décision comestible maladroite pour une langue à typage dynamique. Si vous voulez tester quelque chose qui peut être nul ou nul, vous finirez par devoir écrire if (thing === 0), ce nest tout simplement pas cool.
  • @HostileFork I don ‘ Je ne sais pas. Je trouve quil est logique que 0 soit true (comme tout autre entier) dans un langage dynamique. Il mest parfois arrivé dattraper un 0 en essayant dattraper None en Python, et cela peut parfois être assez difficile à repérer.
  • Ruby nest pas une valeur aberrante. Ruby tire cela de Lisp (Ruby est même secrètement appelé  » MatzLisp « ). Lisp est un langage courant en informatique. Zéro est également juste une valeur vraie dans le shell POSIX, car ‘ est un morceau de texte: if [ 0 ] ; then echo this executes ; fi. La valeur de données fausses est une chaîne vide, et une fausseté testable est un état darrêt échoué dune commande, qui est représenté par un non -zéro.

Réponse

Avant daborder le cas général, nous pouvons discuter de vos exemples de compteur.

Comparaisons de chaînes

Il en va de même pour de nombreux types de comparaisons, en fait. De telles comparaisons calculent une distance entre deux objets. Lorsque les objets sont égaux, la distance est minimale. Ainsi, lorsque la « comparaison réussit », la valeur est 0. Mais en réalité, la valeur de retour de strcmp nest pas un booléen, cest une distance, et que ce qui empêche les programmeurs inconscients de faire if (strcmp(...)) do_when_equal() else do_when_not_equal().

En C ++, nous pourrions reconcevoir strcmp pour renvoyer un Distance, qui remplace operator bool() pour renvoyer true quand 0 (mais vous seriez alors mordu par un autre ensemble de problèmes). Ou en C pur, ayez simplement une fonction streq qui renvoie 1 lorsque les chaînes sont égales, et 0 sinon.

Appels API / code de sortie du programme

Ici, vous vous souciez de la raison pour laquelle quelque chose sest mal passé, car cela entraînera les décisions en cas derreur. Lorsque les choses réussissent, vous ne voulez rien savoir en particulier – votre intention est réalisée. La valeur de retour doit donc transmettre cette information.Ce nest pas un booléen, cest un code derreur. La valeur derreur spéciale 0 signifie « pas derreur ». Le reste de la plage représente les erreurs significatives localement que vous devez traiter (y compris 1, qui signifie souvent « erreur non spécifiée »).

Cas général

Ceci nous laisse avec la question: pourquoi les valeurs booléennes sont-elles True et False généralement représenté avec 1 et 0, respectivement?

Eh bien, en plus de largument subjectif « ça va mieux comme ça », voici quelques raisons (subjectives aussi) auxquelles je peux penser: p>

  • Analogie du circuit électrique. Le courant est activé pendant 1 s et désactivé pendant 0 s. Jaime avoir (1, Yes, True, On) ensemble et (0, No, False, Off), plutôt quun autre mélange

  • initialisations de mémoire. Quand je memset(0) un tas de variables (que ce soit des entiers, des flottants, des booléens), je veux que leur valeur corresponde aux hypothèses les plus conservatrices. Par exemple. ma somme est initialement de 0, le prédicat est False, etc.

Peut-être que toutes ces raisons sont liées à mon éducation – si on mavait appris à associer 0 à True à partir du au début, jirais pour linverse.

Commentaires

  • En fait, il y a au moins un langage de programmation qui traite 0 comme vrai. Le shell Unix.
  • +1 pour résoudre le vrai problème: la plupart des questions de Morwenn ‘ sont n ‘ t à propos de bool du tout.
  • @ dan04 Cest vrai. Le message entier porte sur la justification du choix de la distribution de int à bool dans de nombreux langages de programmation. Les trucs de comparaison et de gestion des erreurs ne sont que des exemples dendroits où le cast dune autre manière que celle quil ‘ fait actuellement aurait du sens.

Réponse

Dun point de vue de haut niveau, vous parlez de trois types de données assez différents:

  1. Un booléen. La convention mathématique dans algèbre booléenne est dutiliser 0 pour false et 1 pour true, il est donc logique de suivre cette convention. Je pense que cette méthode est également plus logique intuitivement.

  2. Le résultat de la comparaison. trois valeurs: <, = et > (notez quaucune delles nest true). Pour eux, il est logique dutiliser les valeurs de -1, 0 et 1, respectivement (ou, plus généralement, une valeur négative, zéro et une valeur positive).

    Si vous voulez vérifier légalité a Si vous navez quune fonction qui effectue une comparaison générale, je pense que vous devriez la rendre explicite en utilisant quelque chose comme strcmp(str1, str2) == 0. Je trouve que lutilisation de ! dans cette situation est déroutante, car elle traite une valeur non booléenne comme sil sagissait dun booléen.

    Aussi, gardez à lesprit cette comparaison et légalité nest pas nécessairement la même chose. Par exemple, si vous classez les personnes par leur date de naissance, Compare(me, myTwin) doit renvoyer 0 , mais Equals(me, myTwin) doit renvoyer false.

  3. Le succès ou léchec dune fonction , éventuellement également avec des détails sur ce succès ou cet échec. Si vous parlez de Windows, ce type est appelé HRESULT et une valeur non nulle nindique pas nécessairement un échec. En fait, une valeur négative indique un échec et une réussite non négative. La valeur de succès est très souvent S_OK = 0, mais cela peut aussi être par exemple S_FALSE = 1, ou dautres valeurs.

La confusion vient du fait que trois logiquement des types de données assez différents sont en fait représentés comme un seul type de données (un entier) en C et dans dautres langages et que vous pouvez utiliser entier dans une condition. Mais je ne pense pas quil serait logique de redéfinir booléen pour simplifier lutilisation de certains types non booléens dans des conditions.

Aussi, considérons un autre type qui est souvent utilisé dans une condition en C: un pointeur . Là, il « est naturel de traiter un NULL -pointer (qui est représenté par 0) comme false. Donc, suivre votre suggestion rendrait également le travail avec des pointeurs plus difficile. (Bien que, personnellement, je préfère comparer explicitement les pointeurs avec NULL, au lieu de les traiter comme des booléens.)

Réponse

Zéro peut être faux car la plupart des CPU ont un drapeau ZERO qui peut être utilisé pour créer des branches. Il enregistre une opération de comparaison.

Voyons pourquoi.

Certains psuedocode, car le public ne lit probablement pas lassemblage

c- source appelle une boucle simple wibble 10 fois

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

un assemblage simulé pour ça

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- source un autre simple boucle appelle wibble 10 fois

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

un assemblage simulé pour ce cas

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 

un peu plus de source c

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

et lassembly

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

voyez à quel point cest court?

un peu plus de source c

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

et lassembly (supposons un compilateur marginalement intelligent qui peut remplacer == 0 sans comparaison )

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

Essayons maintenant une convention de true = 1

un peu plus c source #define TRUE 1 int foo = TRUE; if (toto == TRUE) wibble ()

et lassembly

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

voyez à quel point le cas avec vrai non nul est court?

Vraiment Les premiers processeurs avaient de petits ensembles dindicateurs attachés à laccumulateur.

Pour vérifier si a> b ou a = b prend généralement une instruction de comparaison.

  • Sauf si B est soit ZERO – auquel cas lindicateur ZERO est mis Implémenté comme un simple NOR logique ou tous les bits de laccumulateur.
  • Ou NÉGATIF dans lequel il suffit dutiliser le « bit de signe » cest-à-dire le bit le plus significatif de laccumulateur si vous utilisez larithmétique du complément à deux. (La plupart du temps nous le faisons)

Répétons ceci. Sur certains processeurs plus anciens, vous navez pas eu à utiliser une instruction de comparaison pour un accumulateur égal à ZERO ou un accumulateur inférieur à zéro.

Maintenant, voyez-vous pourquoi zéro pourrait être faux?

Veuillez noter quil sagit de psuedo-code et quaucun jeu dinstructions ne ressemble vraiment à ceci. Si vous connaissez lassemblage, vous savez que je simplifie beaucoup les choses ici. Si vous savez quelque chose sur la conception du compilateur, vous navez pas besoin de lire cette réponse. Quiconque sait quelque chose sur le déroulement de boucle ou la prédiction de branche, la classe avancée est au bout du couloir dans la salle 203.

Commentaires

  • Votre argument nest pas bien fait ici car pour une chose if (foo) et if (foo != 0) devrait générer le même code, et deuxièmement, vous ‘ montrer que le langage dassemblage que vous ‘ utilisez est en fait explicite opérandes booléens et les teste. Par exemple, jz signifie jump if zero. En dautres termes if (a == 0) goto target; . Et la quantité nest même pas testée directement; la condition est convertie en un drapeau booléen qui est stocké dans un mot machine spécial. Elle ‘ ressemble plus à cpu.flags.zero = (a == 0); if (cpu.flags.zero) goto target;
  • Pas de Kaz, les anciens processeurs ‘ ne fonctionnaient pas comme ça. T Le jz / jnz peut être exécuté sans faire une instruction de comparaison. Cétait vraiment le but de tout mon message.
  • Je nai ‘ rien écrit sur une instruction de comparaison.
  • Pouvez-vous citer un processeur qui a une instruction jz mais pas de jnz? (ou tout autre ensemble asymétrique dinstructions conditionnelles)

Réponse

De nombreuses réponses suggèrent que la correspondance entre 1 et vrai est rendue nécessaire par une propriété mathématique. Je ne peux pas trouver une telle propriété et suggérer quil sagit dune convention purement historique.

Étant donné un champ avec deux éléments, nous avons deux opérations: laddition et la multiplication. Nous pouvons mapper les opérations booléennes sur ce champ de deux manières :

Traditionnellement, nous identifions True avec 1 et False avec 0. Nous identifions AND avec * et XOR avec +. Ainsi OR est une addition saturante.

Cependant, nous pourrions tout aussi bien identifiez Vrai avec 0 et Faux avec 1. Ensuite, nous identifions OR avec * et XNOR avec +. Ainsi AND est une addition saturante.

Commentaires

  • Si vous aviez suivi le lien sur wikipedia vous auriez pu constater que le concept dalgèbre booléenne est fermé lié à celui dun champ de Galois à deux éléments ( en.wikipedia.org/wiki / GF% 282% 29 ). Les symboles 0 et 1 sont traditionnellement utilisés pour désigner respectivement les identités additive et multiplicative, car les nombres réels sont aussi un champ dont les identités sont les nombres 0 et 1.
  • @NeilG Je pense que Giorgio essaie de dire que ‘ est plus quune simple convention. 0 et 1 en algèbre booléenne sont fondamentalement les mêmes que 0 et 1 dans GF (2), qui se comportent presque comme 0 et 1 en nombres réels en ce qui concerne laddition et la multiplication.
  • @svick: Non , parce que vous pouvez simplement renommer la multiplication et laddition saturante en OR et AND, puis retourner les étiquettes de sorte que 0 soit vrai et 1 soit faux.Giorgio dit que cétait une convention de logique booléenne, qui a été adoptée comme convention de linformatique.
  • @Neil G: Non, vous ne pouvez pas retourner + et * et 0 et 1 car un champ nécessite une distributivité de multiplication sur addition (voir en.wikipedia.org/wiki/Field_%28mathematics%29 ), mais si vous définissez +: = AND et *: = XOR , vous obtenez T XOR (T AND F) = T XOR F = T, alors que (T XOR T) AND (T XOR F) = F AND T = F.Par conséquent, en inversant les opérations et les identités, vous navez pas de champ plus. Donc, lOMI définissant 0 et 1 comme identités dun champ approprié semble capturer assez fidèlement le faux et le vrai.
  • @giorgio: jai modifié la réponse pour rendre évident ce qui se passe.

Réponse

Étrangement, zéro nest pas toujours faux.

En particulier, la convention Unix et Posix consiste à définir EXIT_SUCCESS comme 0 (et EXIT_FAILURE comme 1). En fait, cest même une convention C standard!

Donc pour les shells Posix et exit (2) syscalls, 0 signifie « réussi », ce qui est intuitivement plus vrai que faux.

En particulier, le shell « s if veut un process return EXIT_SUCCESS (soit 0) pour suivre sa branche « then »!

Dans Scheme (mais pas en Common Lisp ou en MELT ) 0 et nul (cest-à-dire () dans Scheme) sont vrais, car la seule valeur fausse est #f

Je suis daccord, je suis tatillon!

Réponse

C est utilisé pour la programmation de bas niveau proche du matériel, une zone dans laquelle vous devez parfois basculer entre les opérations binaires et logiques, sur les mêmes données. Être obligé de convertir une expression numérique en booléen juste pour effectuer un test encombrerait le code.

Vous pouvez écrire des choses comme:

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

plutôt que

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

Dans un exemple isolé, ce nest pas si mal, mais devoir faire cela deviendra ennuyeux.

De même, les opérations inverses. Il est utile que le résultat dune opération booléenne, comme une comparaison, produise simplement un 0 ou un 1: Supposons que nous voulions définir le troisième bit dun mot selon que modemctrl a le bit de détection de porteuse:

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

Ici, nous devons avoir le != 0, pour réduire le résultat de lexpression bidirectionnelle & à 0 ou 1, mais comme le résultat nest quun entier, nous sommes épargnés davoir à ajouter une conversion ennuyeuse pour convertir davantage le booléen en entier.

Même si le C moderne a maintenant un bool, il préserve toujours la validité dun code comme celui-ci, à la fois parce que cest « une bonne chose » et à cause de la rupture massive de compatibilité ascendante qui serait causée autrement.

Un autre exemple où C est lisse: tester deux conditions booléennes comme un commutateur à quatre voies:

Vous ne pourriez pas enlever cela au programmeur C sans combat!

Enfin, C sert parfois comme une sorte de langage dassemblage de haut niveau. Dans les langages dassemblage, nous navons pas non plus de types booléens. Une valeur booléenne est juste un bit ou une valeur zéro par rapport à zéro dans un emplacement de mémoire ou un registre. Un entier zéro, un zéro booléen et ladresse zéro sont tous testés de la même manière dans les jeux dinstructions en langage assembleur (et peut-être même zéro à virgule flottante). La ressemblance entre C et le langage dassemblage est utile, par exemple lorsque C est utilisé comme langage cible pour compiler un autre langage (même celui qui a des booléens fortement typés!)

Réponse

Une valeur booléenne ou de vérité na que 2 valeurs. Vrai et faux.

Ceux-ci doivent pas être représentés sous forme dentiers, mais sous forme de bits (0 et 1 ).

Dire tout autre entier à côté de 0 ou 1 nest pas faux est une déclaration déroutante. Les tables de vérité traitent des valeurs de vérité, pas des entiers.

À partir dune valeur de vérité prospective, -1 ou 2 briserait toutes les tables de vérité et toute logique booléenne associée.

  • 0 AND -1 ==?!
  • 0 OU 2 ==?!

La plupart des langues ont généralement un boolean type qui, lorsquil est converti en un type numérique tel quun entier, révèle faux pour être converti en une valeur entière de 0.

Commentaires

  • 0 AND -1 == quelle que soit la valeur booléenne vers laquelle vous les convertissez. Cest ‘ que porte ma question, pourquoi les convertir en TRUE ou FALSE.Je nai jamais dit – peut-être que je lai fait, mais ce nétait pas prévu – les entiers étaient vrais ou faux, jai demandé pourquoi ils sévaluaient à celui qui était converti en booléen.

Réponse

En fin de compte, vous parlez de casser le langage de base parce que certaines API sont merdiques. Les API Crappy ne sont pas nouvelles, et vous ne pouvez pas les corriger en cassant le langage. Cest un fait mathématique que 0 est faux et 1 est vrai, et tout langage qui ne respecte pas cela est fondamentalement cassé. La comparaison à trois est niche et na aucune entreprise ayant son résultat converti implicitement en bool car il renvoie trois résultats possibles. Les anciennes API C ont simplement une gestion des erreurs terrible, et sont également paralysées parce que C na pas les fonctionnalités de langage nécessaires pour ne pas avoir dinterfaces terribles.

Notez que je ne dis pas cela pour les langages qui nont pas dimplicite integer-> conversion booléenne.

Commentaires

  •  » Cest un fait mathématique que 0 est faux et 1 est vrai  » Erm.
  • Pouvez-vous citer une référence pour votre  » fait mathématique que 0 est faux et 1 est vrai « ? Votre réponse ressemble dangereusement à une diatribe.
  • Ce ‘ n’est pas un fait mathématique, mais cela ‘ une convention mathématique depuis le 19ème siècle.
  • Lalgèbre booléenne est représentée par un corps fini dans lequel 0 et 1 sont les éléments didentité pour les opérations qui ressemblent à laddition et à la multiplication. Ces opérations sont respectivement OR et AND. En fait, lalgèbre booléenne sécrit un peu comme lalgèbre normale où la juxtaposition dénote ET, et le symbole + dénote OR. Par exemple, abc + a'b'c signifie (a and b and c) or (a and (not b) and (not c)).

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *