web-dev-qa-db-fra.com

Pourquoi 0 est-il faux?

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

Comparaison de chaînes

Étant donné que la question semble un peu trop simple, je vais m'expliquer un peu plus: tout d'abord, cela peut sembler évident à tout programmeur, mais pourquoi n'y aurait-il pas de langage de programmation - il peut y en avoir, mais pas n'importe lequel J'ai utilisé - où 0 évalue à true et toutes les autres valeurs [entières] à false? Cette remarque peut sembler aléatoire, mais j'ai quelques exemples où cela a peut-être été une bonne idée. Tout d'abord, prenons l'exemple de la comparaison tripartite des chaînes, je prendrai le strcmp de C comme exemple: tout programmeur essayant C comme sa première langue peut être tenté d'écrire le code suivant:

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

Puisque strcmp renvoie 0 qui correspond à 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. Eu 0 évaluée à 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 n'aurait été fait qu'en cas de besoin. 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 des valeurs -1, 0 et 1. Cela peut être assez pratique. Imaginez qu'il y ait un opérateur de vaisseau spatial en C++ et nous le voulons pour std::string (enfin, il y a déjà la fonction compare, mais l'opérateur du vaisseau spatial est plus amusant). La déclaration serait actuellement la suivante:

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

Eu 0 a été évalué en true, l'opérateur du vaisseau spatial n'existerait même pas, et nous aurions pu déclarer operator== de cette façon:

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

Cette operator== aurait géré la comparaison à trois à la fois, et pourrait toujours être utilisé pour effectuer la vérification suivante tout en étant en mesure de vérifier quelle chaîne est lexicographiquement supérieure à l'autre si nécessaire:

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

Gestion des anciennes erreurs

Nous avons maintenant des exceptions, donc cette partie ne s'applique qu'aux anciennes langues où rien de tel n'existe (C par exemple). Si nous regardons la bibliothèque standard de C (et POSIX aussi), nous pouvons voir avec certitude que les fonctions maaaaany retournent 0 en cas de succès et tout entier sinon. J'ai malheureusement vu des gens faire 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 en programmation, nous avons souvent le schéma de raisonnement suivant:

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

Si nous y repensons, il aurait été judicieux de mettre la seule valeur neutre, 0, à yes (et c'est ainsi que fonctionnent les fonctions de C), tandis 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 certains langages ésothériques expérimentaux), que yes est évalué à false dans une condition if, tandis que tous les no les cas sont é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 on y pense de cette façon, avoir 0 évaluer à true et le reste à false aurait été beaucoup plus logique.

Conclusion

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

Suivi: C'est bien de voir qu'il y a beaucoup de réponses avec beaucoup d'idées et autant de raisons possibles pour que ce soit comme ça. J'adore à quel point vous semblez être passionné. J'ai initialement posé cette question par ennui, mais comme vous semblez si passionné, j'ai décidé d'aller un peu plus loin et de poser des questions sur la logique derrière le choix booléen pour 0 et 1 sur Math.SE :)

119
Morwenn

0 est false car ils sont tous les deux des éléments zéro en commun demi-anneaux . Même s'il s'agit de types de données distincts, il est logique de les convertir entre eux car ils appartiennent à des structures algébriques isomorphes.

  • 0 est l'identité pour l'addition et zéro pour la multiplication. Cela 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 l'identité pour les booléens xor (⊻) et zéro pour les booléens et (∧). Si les booléens sont représentés par {0, 1} - l'ensemble des entiers modulo 2 - vous pouvez penser à ⊻ comme addition sans report et ∧ comme multiplication.

  • "" et [] sont des identités pour la concaténation, mais il existe plusieurs opérations pour lesquelles elles ont un sens égal à zéro. La répétition en est un, 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 l'ensemble, les programmes peuvent être plus difficiles à raisonner. Un des nombreux compromis dans la conception de langage.

103
Jon Purdy

Parce que les mathématiques fonctionnent.

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

... insert many other examples here.

Traditionnellement, les programmes C ont des conditions comme

if (someFunctionReturningANumber())

plutôt que

if (someFunctionReturningANumber() != 0)

parce que le concept de zéro étant équivalent à faux est bien compris.

75
Robert Harvey

Comme d'autres l'ont dit, le calcul est venu en premier. C'est pourquoi 0 est false et 1 est true.

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

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

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

39
joshin4colours

Je pensais que cela avait à voir avec "l'héritage" de l'électronique, et aussi l'algè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 qu'il fait est de calculer la "distance" entre les deux chaînes. Le fait que 0 soit également considéré comme faux n'est qu'une coïncidence.

renvoyer en cas de succès est logique car 0 dans ce cas est utilisé pour signifier aucune erreur et tout autre nombre serait une erreur code. L'utilisation d'un autre numéro pour réussir aurait moins de sens puisque vous n'avez qu'un seul code de réussite, alors que vous pouvez avoir plusieurs codes d'erreur. Vous utilisez "Cela a-t-il fonctionné?" comme l'expression de l'instruction if et dire 0 = oui aurait plus de sens, mais l'expression est plus correctement "Est-ce que quelque chose s'est mal passé?" et puis vous voyez que 0 = non a beaucoup de sens. Penser à false/true n'a pas vraiment de sens ici, car c'est en fait no error code/error code.

27
Svish

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 Galois (champ fini) de deux éléments (voir ici ).

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

Les symboles 0 et 1 sont classiquement utilisés pour désigner les identités additives et multiplicatives d'un champ car les nombres réels sont également un champ (mais pas fini) dont les identités sont les nombres 0 et 1.

L'identité additive est l'élément 0 du champ, tel que pour tout x:

x + 0 = 0 + x = x

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

x * 1 = 1 * x = x

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

Remarque. Si vous inversez les opérations (XOR est la multiplication et AND est l'addition), alors la multiplication n'est pas distributive sur l'addition et vous n'avez pas de champ plus. Dans un tel cas, vous n'avez aucune raison d'appeler les deux éléments 0 et 1 (dans n'importe quel ordre). Notez également que vous ne pouvez pas choisir l'opération OR au lieu de XOR: peu importe la façon dont vous interprétez OR/AND comme addition/multiplication, la structure résultante n'est pas un champ (tous les éléments inverses n'existent pas comme requis par les axiomes de champ).

Concernant les fonctions C:

  • De nombreuses fonctions renvoient un entier qui est un code d'erreur. 0 signifie PAS D'ERREUR.
  • Intuitivement, la fonction strcmp calcule la différence entre deux chaînes. 0 signifie qu'il n'y a pas de différence entre deux chaînes, c'est-à-dire que deux chaînes sont égales.

Les explications intuitives ci-dessus peuvent aider à se souvenir de l'interprétation des valeurs de retour, mais il est encore plus facile de simplement vérifier la documentation de la bibliothèque.

18
Giorgio

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

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

L'exemple de shells traitant un état de sortie 0 comme vrai 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 qu'il y a une façon de réussir, mais de nombreuses façons d'échouer, donc l'utilisation de 0 comme valeur spéciale signifiant "pas d'erreur" est pragmatique.

Ruby: 0 est comme n'importe quel autre nombre

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

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

justification est que seuls false et nil doivent être faux. Pour de nombreux Ruby novices, c'est un piège. Cependant, dans certains cas, c'est bien que 0 soit traité comme n'importe 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 en tant que type distinct des nombres. Dans les premiers temps de l'informatique, les programmeurs travaillant avec le langage d'assemblage ou le langage machine brut n'avaient pas de tels luxes. Il est probablement tout à fait naturel de traiter 0 comme l'état "vide" et de définir un bit sur 1 comme indicateur lorsque le code a détecté que quelque chose s'est produit. Par extension, la convention a développé que zéro était traité comme faux et que les valeurs non nulles étaient considéré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 ( Java Language Specification, Sec 4.2.2 ):

Il n'y a pas de transtypage entre les types intégraux et le type boolean.

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

14
200_success

Avant d'aborder le cas général, nous pouvons discuter de vos contre-exemples.

Comparaisons de chaînes

La même chose vaut pour de nombreuses sortes de comparaisons, en fait. De telles comparaisons calculent une distance entre deux objets. Lorsque les objets sont égaux, la distance est minimale. Donc quand la "comparaison réussit", la valeur est 0. Mais vraiment, la valeur de retour de strcmp est pas un booléen, c'est une distance, et ce que les pièges ignorent programmeurs faisant if (strcmp(...)) do_when_equal() else do_when_not_equal().

En C++, nous pourrions repenser strcmp pour renvoyer un objet Distance, qui remplace operator bool() pour retourner vrai quand 0 (mais vous seriez alors mordu par un ensemble différent de problèmes) . Ou en C simple, il suffit d'avoir 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 s'est mal passé, car cela entraînera des erreurs. Lorsque les choses réussissent, vous ne voulez rien savoir de particulier - votre intention se réalise. La valeur de retour doit donc véhiculer cette information. C'est pas un booléen, c'est un code d'erreur. La valeur d'erreur spéciale 0 signifie "pas d'erreur". Le reste de la plage représente des erreurs significatives localement que vous devez traiter (dont 1, qui signifie souvent "erreur non spécifiée").

Cas général

Cela nous laisse avec la question: pourquoi les valeurs booléennes True et False sont-elles communément représentées par 1 et 0, respectivement?

Eh bien, en plus de l'argument subjectif "on se sent mieux de cette façon", voici quelques raisons (subjectives également) auxquelles je peux penser:

  • analogie du circuit électrique. Le courant est activé pendant 1 s et désactivé pendant 0 s. J'aime avoir (1, Oui, True, On) ensemble et (0, Non, False, Off), plutôt qu'un autre mix

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

Peut-être que toutes ces raisons sont liées à mon éducation - si on m'avait appris à associer 0 à True depuis le début, j'irais dans l'autre sens.

8
user44761

D'un point de vue de haut niveau, vous parlez de trois types de données très différents:

  1. Un booléen. La convention mathématique dans Algèbre booléenne est d'utiliser 0 pour false et 1 pour true, il est donc logique de suivre cette convention. Je pense que cette manière a également plus de sens intuitivement.

  2. Le résultat de la comparaison. Cela a trois valeurs: <, = Et > (Notez qu'aucune d'entre elles n'est true). Pour eux, il est logique d'utiliser 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é et que vous n'avez qu'une 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 l'utilisation de ! Dans cette situation déroutante, car elle traite une valeur non booléenne comme si elle était booléenne.

    Gardez également à l'esprit que la comparaison et l'égalité ne doivent pas nécessairement être la même chose. Par exemple, si vous triez les personnes par date de naissance, Compare(me, myTwin) doit renvoyer 0, Mais Equals(me, myTwin) doit renvoyer false.

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

La confusion vient du fait que trois types de données logiquement très différents sont en fait représentés comme un seul type de données (un entier) en C et dans d'autres langages et que vous pouvez utiliser un entier dans une condition. Mais je ne pense pas qu'il serait logique de redéfinir booléen pour rendre l'utilisation de certains types non booléens dans des conditions plus simples.

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

6
svick

Zéro peut être faux car la plupart des processeurs ont un indicateur ZÉRO qui peut être utilisé pour se ramifier. Il enregistre une opération de comparaison.

Voyons pourquoi.

Certains pseudo-code, car le public ne lit probablement pas Assembly

c- les appels de boucle simple source oscillent 10 fois

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

certains prétendent l'Assemblée pour cela

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

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

certains prétendent l'Assemblée 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 l'Assemblée

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

voyez combien c'est court?

un peu plus de source c

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

et l'assemblage (supposons un compilateur légèrement intelligent qui puisse 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 de source c #define TRUE 1 int foo = TRUE; if (foo == TRUE) wibble ()

et l'Assemblée

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?

Très tôt, les processeurs avaient de petits ensembles de drapeaux attachés à l'accumulateur.

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

  • Sauf si B est soit ZÉRO - auquel cas le drapeau ZÉRO est défini Implémenté comme un simple NOR ou tous les bits dans l'accumulateur.
  • Ou NÉGATIF ​​dans lequel il suffit d'utiliser le "bit de signe", c'est-à-dire le bit le plus significatif de l'accumulateur si vous utilisez l'arithmétique du complément à deux. (Surtout nous le faisons)

Reprenons cela. Sur certains CPU plus anciens, vous n'aviez pas à utiliser une instruction de comparaison pour l'accumulateur égale à ZERO, ou un accumulateur inférieur à zéro.

Voyez-vous maintenant pourquoi zéro pourrait être faux?

Veuillez noter qu'il s'agit de code pseudo et qu'aucun jeu d'instructions réel ne ressemble à cela. Si vous connaissez l'assemblage, vous savez que je simplifie beaucoup les choses ici. Si vous savez quelque chose sur la conception du compilateur, vous n'avez pas besoin de lire cette réponse. Quiconque sait quoi que ce soit sur le déroulement des boucles ou la prédiction de branche, la classe avancée est dans le couloir dans la salle 203.

4
Tim Williscroft

Étrangement, zéro n'est pas toujours faux.

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

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

En particulier, if du Shell veut un retour de processus EXIT_SUCCESS (soit 0) pour suivre sa branche "alors"!

Dans le schéma (mais pas dans LISP commun ou dans FONDRE ) 0 et zéro (c'est-à-dire () dans Scheme) sont vraies, car la seule fausse valeur est #f

Je suis d'accord, je taquine!

3

Il y a beaucoup de réponses qui 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 que c'est une convention purement historique.

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

Traditionnellement, nous identifions Vrai avec 1 et Faux avec 0. Nous identifions ET avec * et XOR avec +. Ainsi OR est une addition saturante).

Cependant, nous pourrions tout aussi bien identifier Vrai avec 0 et Faux avec 1. Ensuite, nous identifions OR avec * et XNOR avec +. Ainsi AND est un ajout saturant.

3
Neil G

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 n'est pas si mal, mais le faire deviendra pénible.

De même, converse les opérations. Il est utile que le résultat d'une opération booléenne, comme une comparaison, produise simplement un 0 ou 1: Supposons que nous voulons définir le troisième bit d'un 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 du biwise & expression à 0 ou 1, mais comme le résultat n'est qu'un entier, nous ne devons pas ajouter de transtypage ennuyeux pour convertir davantage le booléen en entier.

Même si le C moderne a maintenant un type bool, il préserve toujours la validité du code comme celui-ci, à la fois parce que c'est une bonne chose, et en raison de la rupture massive avec une compatibilité descendante qui serait causée autrement.

Un autre exemple où C est lisse: tester deux conditions booléennes en tant que commutateur à quatre voies:

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;
}

Vous ne pourriez pas retirer cela au programmeur C sans vous battre!

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

3
Kaz

Une valeur booléenne ou vérité n'a que 2 valeurs. Vrai et faux.

Ceux-ci devraient pas être représentés comme des entiers, mais comme des bits (0 et 1).

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

Du point de vue de la valeur de la vérité, -1 ou 2 briseraient toutes les tables de vérité et toute logique booléenne qui leur serait associée.

  • 0 ET -1 ==?!
  • 0 OR 2 ==?!

La plupart des langues ont généralement un type boolean qui, lorsqu'il est converti en un type numérique tel que entier, révèle que false doit être converti en une valeur entière de 0.

0
Jon Raynor