Pourquoi (0 <5 <3) retourne vrai?


348

Je jouais sur jsfiddle.net et je suis curieux de savoir pourquoi cela revient vrai?

if(0 < 5 < 3) {
    alert("True");
}

Il en va de même:

if(0 < 5 < 2) {
    alert("True");
}

Mais cela ne veut pas:

if(0 < 5 < 1) {
    alert("True");
}

Cette bizarrerie est-elle jamais utile?


12
Connaissez-vous wtfjs.com ?
Harmen

1
Ha! Non, je n'avais jamais vu ça auparavant.
punkrockbuddyholly

Ah, les joies des conversions de types implicites.
Jörg W Mittag

4
Toujours utile? Peut-être pour l'obscurcissement. :-)
Icode4food

Pourquoi? De plus, tout est utile si vous ne trouvez que les circonstances qui l'exigent. Certes, celui-ci est moins souvent requis que de nombreux autres, mais il peut y avoir des moments, peu nombreux et éloignés, où ils peuvent être exactement l'outil pour le travail.
temporaire_user_name

Réponses:


440

L'ordre des opérations entraîne (0 < 5 < 3)l'interprétation en javascript de ((0 < 5) < 3)ce qui produit (true < 3)et true est compté comme 1, ce qui renvoie true.

C'est aussi pourquoi (0 < 5 < 1)renvoie false, (0 < 5)retourne true, ce qui est interprété comme 1résultant en (1 < 1).


158
Et parce que JavaScript n'est PAS Python. :-)
rsenna

1
Vous avez répondu pendant que je modifiais ma question pour ajouter le if(0 < 5 < 1) == false. Tout est clair maintenant, merci :)
punkrockbuddyholly

28
Exactement, Python est le seul langage que je connaisse qui traite cette syntaxe ((0 < 5) && (5 < 3)), il y en a probablement d'autres mais je ne les connais pas.
Alan Geleynse

18
@Alan: Mathematica est un autre exemple.
Joren

2
À mon humble avis, JavaScript devrait déclencher TypeError lorsque vous essayez de comparer un booléen avec un nombre, car cela n'a aucun sens.
Michał Perłakowski

63

Je suppose que c'est parce que 0 < 5c'est vrai, et true < 3est jeté sur 1 < 3ce qui est vrai.


7
Il n'y a pas de casting ici. Un transtypage est un opérateur que le programmeur utilise pour vérifier explicitement un type. Il s'agit d' une conversion implicite d'un booléen en un entier.
erickson

4
@erickson, vraiment ... avons-nous besoin d'être accroché à la sémantique ici?
CaffGeek

2
Ne t'inquiète pas pour Erickson. J'abuse aussi le mot sémantique. :)
Mateen Ulhaq

9
Dans tous les cas, le terme correct est coercition . Et oui, Erickson a partiellement tort avec sa certitude absolue. Une coercition est en tout cas une sorte de transtypage également si généralement (mais ce n'est qu'une convention) vous utilisez le mot "transtypage" pour exprimer des conversions de type explicites. Conversion de type == Casting de type.
Jack

1
Sophistes jusqu'au bout ... La réponse est "laconiquement" sympa quand même;)
Arman McHitarian

21

probablement parce trueest prise comme 1si

0 < 5 < 3  -->  true < 3 -->  1 < 3  --> true


10

Quant à votre question de savoir si cette bizarrerie est jamais utile: je suppose qu'il pourrait y avoir un cas où elle serait utile (si le code condensé est ce que vous recherchez), mais le fait de vous y fier réduira (très probablement) considérablement la compréhensibilité de votre code.

C'est un peu comme utiliser post / pre increment / decrement dans le cadre d'expressions plus grandes. Pouvez-vous déterminer le résultat de ce code en un coup d'œil?

int x = 5;
int result = ++x + x++ + --x;

Remarque: avec ce code, vous pouvez parfois même obtenir des résultats différents selon la langue et le compilateur.

C'est une bonne idée de vous faciliter la vie et celle du prochain gars qui lira votre code. Écrivez clairement ce que vous voulez réellement faire, plutôt que de vous fier à des effets secondaires comme la conversion implicite des booléens.


Par curiosité, a result18 ans?
punkrockbuddyholly

5
@MrMisterMan: Je ne suis pas certain de Javascript, mais en Java et C # l'évaluation est garantie de gauche à droite, et le résultat est en effet 18. Dans certains langages, comme C et C ++, il n'y a aucune garantie que ce sera évalué de gauche à droite, et vous pouvez vous retrouver avec des résultats différents selon les optimisations ajoutées par votre compilateur.
Zach Johnson

9

La réponse à la deuxième partie de la question, "cette bizarrerie est-elle jamais utile?" est peut-être non, comme indiqué dans une réponse précédente, si c'est bien une bizarrerie du langage (Javascript) que true est converti en 1, mais que le programmeur ne voit pas en général 1 et true (et 0 et false) comme même chose.

Si toutefois vous avez un modèle mental où 1 est vrai et 0 est faux, cela conduit à toutes sortes de belles techniques booléennes qui sont extrêmement utiles, puissantes et directes. Par exemple, vous pouvez incrémenter un compteur directement avec le résultat de A> 100, ce qui incrémenterait le compteur si A est supérieur à 100. Cette technique peut être considérée comme une bizarrerie ou une astuce en Java, mais dans un tableau ou un langage fonctionnel. peut être idiomatique.

Un exemple classique dans le langage de tableau APL serait de compter le nombre d'éléments dans un tableau qui sont (disons) supérieurs à 100:

+/A>100

Où si A est le tableau de 5 éléments 107 22256110 3 alors:

A>100

donne le tableau booléen à 5 éléments:

1 0 1 1 0

et en sommant ce résultat booléen:

+/1 0 1 1 0

donne la réponse finale:

3

Cette question est un exemple parfait où cette technique serait très utile, surtout si le problème est généralisé pour déterminer si n sur m valeurs booléennes sont vraies.

Vérifiez si au moins deux booléens sur trois sont vrais


7

C'est facile.

(0 < 5 < 3)

Commencez de gauche à droite pour évaluer le premier 0 <5. Est-ce vrai? Oui. Puisque TRUE = 1, il évalue 1 <3. Puisque 1 est inférieur à 3, c'est vrai.

Maintenant avec ça

 (0 < 5 < 1)

0 est-il inférieur à 5? Oui. Donc, faites-le VRAI, ce qui signifie également 1. Maintenant, avec ce fait à l'esprit, il est évalué à (1 <1). Est-ce que 1 est inférieur à 1? Non, donc c'est faux. Cela doit être égal.


4

évalue-t-il 0 <5 qui retournerait 1 pour vrai quand 1 <3 qui est vrai?

C # veut vous laisser faire ceci "L'opérateur '<' ne peut pas être appliqué aux opérandes de type 'bool' et 'int'"


Parfois, la rigueur de C # me manque dans les langages dynamiques.
Arman McHitarian

4

Je l'ai rencontré il y a quelque temps à Obj-C et j'ai été très perplexe. J'ai obtenu les résultats que je voulais en faisant quelque chose comme ceci:

if(0 < 5  && 5 < 3) {
alert("True");}

Ce qui est bien sûr faux afin que vous n'obteniez pas cette "vraie" alerte. Heureux d'avoir lu ceci, je sais maintenant pourquoi.


4

En plus de python, CoffeeScript est un autre langage qui prend en charge les comparaisons chaînées, donc 3 < x < 10serait converti (3 < x && x < 10)en vanilla JS



1

Un opérande booléen lorsqu'il est opéré sur un opérateur mathématique renvoie un nombre. pour vérifier cela, nous le faisons

true + 1  which gives you 2.

Ainsi 0 < 5, le booléen retourné (vrai) opéré avec l'opérateur mathématique (<) renverra un nombre. Il revient donc à 1 <3 qui renvoietrue


1

parce que 0 est inférieur à 5 alors cela renvoie vrai, et par défaut vrai est tout ce qui inclut et peut être évalué à 1 qui est toujours inférieur à 3 qui retourne à nouveau vrai


0

essayez de formuler vos résultats sous forme de nombre ()

if(Number(0) < Number(5) < Number(3)) {
    alert("True");
}

ou essayez ceci:

if(Number(0) < Number(5) && Number(5) < Number(3)) {
    alert("True");
}

J'ai googlé ceci parce que j'obtenais (3 >= 20) //returning trueet je suppose que javascript essayait de vérifier en 3tant que booléen parce que j'obtenais cette valeur de la elm.getAttribute();fonction qui console.log();imprimait sous forme de chaîne.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.