Почему (0 <5 <3) возвращает true?


348

Я играл в jsfiddle.net, и мне любопытно, почему это возвращает true?

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

Так же это:

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

Но это не так:

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

Это чудак когда-либо полезен?


12
Вы знаете wtfjs.com ?
Хармен

1
Ха! Нет, я никогда не видел этого раньше.
punkrockbuddyholly

Ах, радости неявных преобразований типов.
Йорг Миттаг

4
Всегда полезно? Возможно для запутывания. :-)
Icode4food

Зачем? Кроме того, все полезно, если вы можете найти только обстоятельства, которые этого требуют. Правда, этот требуется реже, чем многие другие, но бывают времена, немногие и далеко между ними, хотя они могут быть именно таким инструментом для работы.
временное_имя_пользователя

Ответы:


440

Порядок операций заставляет (0 < 5 < 3)быть интерпретированным в javascript как ((0 < 5) < 3)производящий, (true < 3)и true считается как 1, заставляя его возвращать true.

Это также, почему (0 < 5 < 1)возвращает false, (0 < 5)возвращает true, что интерпретируется как 1, в результате (1 < 1).


158
И потому, что JavaScript это не Python. :-)
rsenna

1
Вы ответили, когда я редактировал свой вопрос, чтобы добавить if(0 < 5 < 1) == false. Теперь все ясно, спасибо :)
punkrockbuddyholly

28
Точно, Python является единственным языком, который я знаю, который рассматривает этот синтаксис как ((0 < 5) && (5 < 3)), возможно, есть другие, но я не знаю их.
Алан Гелейнсе

18
@ Алан: Mathematica - еще один пример.
Joren

2
ИМХО JavaScript должен вызывать TypeError при попытке сравнить логическое число с числом, потому что это не имеет смысла.
Михал Перлаковский

63

Мое предположение, потому что 0 < 5это правда, и true < 3получает приведение к 1 < 3правде.


7
Здесь нет кастинга. Приведение - это оператор, который программист использует для явной проверки типа. Это неявное преобразование из логического значения в целое.
Эриксон

4
@erickson, правда ... НУЖНО ли мы зацикливаться на семантике здесь?
CaffGeek

2
Не беспокойся об Эриксоне. Я тоже неправильно употребляю слово семантическое. :)
Mateen Ulhaq

9
В любом случае правильный термин - принуждение . И да, Эриксон частично не прав с абсолютной уверенностью. Принуждение в любом случае является своего рода приведением, даже если обычно (но это просто соглашение) вы используете слово «приведение» для выражения явных преобразований типов. Тип преобразования == Тип приведения.
Джек,

1
Софисты на всем пути ... Ответ «лаконично» в любом случае хорош;)
Арман МакХитариан

21

вероятно, потому что trueпредполагается, что 1так

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


10

Что касается вашего вопроса, является ли эта причуда когда-либо полезной: я предполагаю, что мог бы быть случай, когда он был бы полезен (если вам нужен сжатый код), но полагаться на него (скорее всего) значительно снизит понятность вашего кода.

Это похоже на использование post / pre increment / decment как части больших выражений. Можете ли вы определить результат этого кода с первого взгляда?

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

Примечание: с помощью этого кода вы можете даже иногда получать разные результаты в зависимости от языка и компилятора.

Хорошая идея - сделать жизнь проще для себя и для следующего парня, который будет читать ваш код. Четко напишите, что вы на самом деле хотите, чтобы произошло, а не полагайтесь на побочные эффекты, такие как неявное преобразование логических значений.


Из любопытства, result18?
punkrockbuddyholly

5
@MrMisterMan: Я не уверен насчет Javascript, но в Java и C # оценка гарантированно слева направо, и результат действительно равен 18. В некоторых языках, таких как C и C ++, нет никаких гарантий, что это будет оценивается слева направо, и вы можете получить разные результаты в зависимости от оптимизаций, добавленных вашим компилятором.
Зак Джонсон

9

Ответ на вторую часть вопроса: "Этот причуды когда-нибудь полезны?" возможно, нет, как отмечалось в предыдущем ответе, если это действительно изюминка языка (Javascript), значение true приведено к 1, но в общем случае программист не использует 1 и true (и 0 и false) как то же самое.

Однако, если у вас есть ментальная модель 1, которая является истинной, а 0 - ложной, то это приводит к всевозможным хорошим логическим методам, которые являются чрезвычайно полезными, мощными и прямыми. Например, вы могли бы увеличить счетчик напрямую с результатом A> 100, что увеличило бы счетчик, если A больше 100. Этот метод можно рассматривать как причуду или уловку в Java, но в массиве или функциональном языке. может быть идиоматическим.

Классическим примером в APL на языке массива будет подсчет количества элементов в массиве, которые, скажем, больше 100:

+/A>100

Где, если A - массив из 5 элементов 107 22 256 110 3, то:

A>100

возвращает логический массив из 5 элементов:

1 0 1 1 0

и суммируем этот логический результат:

+/1 0 1 1 0

дает окончательный ответ:

3

Этот вопрос является прекрасным примером того, где этот метод был бы очень полезен, особенно если задача обобщена, чтобы определить, истинны ли n из m булевых значений.

Проверьте, верно ли хотя бы два из трех логических значений


7

Это легко.

(0 < 5 < 3)

Начните с слева направо, чтобы оценить первые 0 <5. Это правда? Да. Так как TRUE = 1, он оценивает 1 <3. Поскольку 1 меньше 3, значит, это правда.

Теперь с этим

 (0 < 5 < 1)

0 меньше 5? Да. Так что сделайте его ИСТИНА, что также означает 1. Теперь, имея в виду этот факт, оно оценивается как (1 <1). 1 меньше 1? Нет, поэтому это неверно. Это должно быть равным.


4

это оценка 0 <5, которая вернула бы 1 для истины, когда 1 <3, который является истиной?

C # хочет позволить вам сделать это "Оператор" <'не может быть применен к операндам типа' bool 'и' int '"


Иногда я скучаю по строгости C # в динамических языках.
Арман Макхитариан

4

Я столкнулся с этим некоторое время назад в Obj-C и был очень озадачен этим. Я получил желаемые результаты, сделав что-то вроде этого:

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

Что, конечно, является ложным, так что вы не получите это «истинное» предупреждение. Рад, что прочитал это, теперь я знаю почему.


4

В дополнение к python, CoffeeScript является еще одним языком, который поддерживает цепные сравнения, поэтому 3 < x < 10будет преобразован (3 < x && x < 10)в vanilla JS.



1

Булевский операнд при работе над математическим оператором возвращает число. чтобы проверить это мы делаем

true + 1  which gives you 2.

Таким образом 0 < 5, возвращенное логическое значение (true), работающее с математическим оператором (<), вернет число. Таким образом, это сводится к 1 <3, который возвращаетtrue


1

потому что 0 меньше 5, то это возвращает true, и по умолчанию true - все, что включает, и может быть оценено как 1, которое все еще меньше 3, что снова возвращает true


0

попробуйте сформулировать свои результаты как число ()

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

или попробуйте это:

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

Я гуглил это, потому что я получал, (3 >= 20) //returning trueи я думаю, что javascript пытался проверить 3как логическое значение, потому что я получал это значение из elm.getAttribute();функции, которая console.log();печатала в виде строки.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.