Por que (0 <5 <3) retorna verdadeiro?


348

Eu estava brincando no jsfiddle.net e estou curioso para saber por que isso retorna verdadeiro?

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

O mesmo acontece com isso:

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

Mas isso não acontece:

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

Essa peculiaridade é sempre útil?


12
Você conhece wtfjs.com ?
Harmen

11
Ha! Não, eu nunca tinha visto isso antes.
precisa

Ah, as alegrias das conversões implícitas de tipo.
Jörg W Mittag

4
Sempre útil? Possivelmente por ofuscação. :-)
Icode4food

Por quê? Além disso, qualquer coisa é útil se você puder encontrar apenas as circunstâncias que a exigem. É verdade que este é menos necessário do que muitos outros, mas há momentos, muito poucos e distantes, onde possam estar, onde pode ser exatamente a ferramenta para o trabalho.
temporary_user_name

Respostas:


440

A ordem das operações faz (0 < 5 < 3)com que seja interpretado em javascript como o ((0 < 5) < 3)que produz (true < 3)e true é contado como 1, fazendo com que ele retorne true.

É também por isso que (0 < 5 < 1)retorna false, (0 < 5)retorna true, que é interpretado como 1resultando em (1 < 1).


158
E porque o JavaScript NÃO é Python. :-)
rsenna

11
Você respondeu enquanto eu estava editando minha pergunta para adicionar o if(0 < 5 < 1) == false. Tudo está claro agora, graças :)
punkrockbuddyholly

28
Exatamente, Python é a única linguagem que conheço que trata essa sintaxe ((0 < 5) && (5 < 3)), pois provavelmente existem outras, mas eu não as conheço.
Alan Geleynse

18
@ Alan: Mathematica é outro exemplo.
Joren

2
O IMHO JavaScript deve gerar TypeError ao tentar comparar booleano com número, porque não faz sentido.
Michał Perłakowski

63

Meu palpite é que 0 < 5é verdade, e true < 3é lançado para o 1 < 3que é verdadeiro.


7
Não há elenco aqui. Uma conversão é um operador que o programador usa para verificar explicitamente um tipo. Isso é conversão implícita de um booleano para um número inteiro.
quer

4
@ erickson, sério ... PRECISAMOS de ficar pendurados na semântica aqui?
CaffGeek #

2
Não se preocupe com Erickson. Também uso indevidamente a palavra semântica. :)
Mateen Ulhaq

9
De qualquer forma, o termo correto é coerção . E sim, Erickson está parcialmente errado com sua absoluta certeza. De qualquer forma, uma coerção também é um tipo de conversão, se normalmente (mas é apenas uma convenção) você usa a palavra "conversão" para expressar conversões de tipo explícitas. Conversão de tipo == Conversão de tipo.
Jack

11
Sofistas todo o caminho ... A resposta é 'laconicamente' bom de qualquer maneira;)
Arman McHitarian

21

provavelmente porque trueé assumido como 1tão

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


10

Quanto à sua pergunta sobre se essa peculiaridade é útil: suponho que possa haver algum caso em que seja útil (se for o que você procura depois de código condensado), mas confiar nele irá (muito provavelmente) reduzir drasticamente a compreensibilidade do seu código.

É como usar pós / pré-incremento / decremento como parte de expressões maiores. Você pode determinar rapidamente qual é o resultado desse código?

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

Nota: com esse código, às vezes você pode obter resultados diferentes dependendo do idioma e do compilador.

É uma boa idéia facilitar a vida para você e o próximo cara que lerá seu código. Escreva claramente o que você realmente quer que aconteça, em vez de depender de efeitos colaterais, como a conversão implícita de booleanos.


Por curiosidade, tem result18 anos?
precisa

5
@MrMisterMan: Não tenho certeza sobre Javascript, mas em Java e C # a avaliação é garantida da esquerda para a direita e o resultado é realmente 18. Em algumas linguagens, como C e C ++, não há garantia de que será avaliado da esquerda para a direita e você pode ter resultados diferentes, dependendo das otimizações adicionadas pelo seu compilador.
Zach Johnson

9

A resposta para a segunda parte da pergunta "essa peculiaridade é sempre útil?" talvez não, como observado em uma resposta anterior, se é realmente uma peculiaridade da linguagem (Javascript) que true é convertido em 1, mas que o programador não vê em geral 1 e true (e 0 e false) como o mesma coisa.

Se, no entanto, você tem um modelo mental de 1 sendo verdadeiro e 0 sendo falso, isso leva a todo tipo de boas técnicas booleanas que são extremamente úteis, poderosas e diretas. Por exemplo, você pode incrementar um contador diretamente com o resultado de A> 100, o que aumentaria o contador se A for maior que 100. Essa técnica pode ser vista como uma peculiaridade ou um truque em Java, mas em uma matriz ou linguagem funcional pode ser idiomático.

Um exemplo clássico no idioma da matriz APL seria contar o número de itens em uma matriz que são (digamos) maiores que 100:

+/A>100

Onde A é a matriz de 5 itens 107 22 256 110 3, então:

A>100

gera a matriz booleana de 5 itens:

1 0 1 1 0

e somando esse resultado booleano:

+/1 0 1 1 0

produz a resposta final:

3

Esta pergunta é um exemplo perfeito de onde essa técnica seria muito útil, especialmente se o problema for generalizado para determinar se n de valores booleanos são verdadeiros.

Verifique se pelo menos dois de três booleanos são verdadeiros


7

Isso é fácil.

(0 < 5 < 3)

Comece da esquerda para a direita para avaliar o primeiro 0 <5. É verdade? Sim. Como TRUE = 1, ele avalia 1 <3. Como 1 é menor que 3, é verdade.

Agora com isso

 (0 < 5 < 1)

0 é menor que 5? Sim. Portanto, torne VERDADEIRO o que também significa 1. Agora, com esse fato em mente, ele avalia como (1 <1). 1 é menor que 1? Não, portanto, é falso. Tem que ser igual.


4

está avaliando 0 <5 que retornaria 1 como verdadeiro quando 1 <3 que é verdadeiro?

C # quer que você faça isso "O operador '<' não pode ser aplicado a operandos do tipo 'bool' e 'int'"


Às vezes, sinto falta do rigor do C # em linguagens dinâmicas.
Arman McHitarian

4

Eu me deparei com isso há pouco tempo no Obj-C e fiquei muito intrigado com isso. Consegui os resultados desejados fazendo algo assim:

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

O que, obviamente, é falso, para que você não receba esse alerta "verdadeiro". Ainda bem que li isso, agora sei o porquê.


4

Além do python, o CoffeeScript é outra linguagem que suporta comparações encadeadas e, portanto, 3 < x < 10seria convertida (3 < x && x < 10)em JS vanilla



1

Um operando booleano quando operado sobre um operador matemático retorna um número. para verificar isso, fazemos

true + 1  which gives you 2.

Portanto 0 < 5, o booleano retornado (true) operado com o operador matemático (<) retornará um número. Então, ele chega a 1 <3, que retornatrue


1

porque 0 é menor que 5, então retorna true, e por padrão true é qualquer coisa que inclua e possa ser avaliado como 1, que ainda é menor que 3, que retorna novamente true


0

tente redigir seus resultados como Number ()

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

ou tente o seguinte:

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

Eu pesquisei isso porque estava recebendo (3 >= 20) //returning truee acho que o javascript estava tentando verificar 3como um booleano porque estava obtendo esse valor da elm.getAttribute();função que console.log();estava sendo impressa no formato String.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.