Dlaczego (0 <5 <3) zwraca wartość true?


348

Bawiłem się w jsfiddle.net i jestem ciekawy, dlaczego to zwraca wartość prawda?

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

Czyni to:

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

Ale to nie:

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

Czy to dziwactwo jest kiedykolwiek przydatne?


12
Czy znasz wtfjs.com ?
Harmen

1
Ha! Nie, nigdy wcześniej tego nie widziałem.
punkrockbuddyholly

Ach, radości z niejawnych konwersji typu.
Jörg W Mittag

4
Czy byłeś kiedyś użyteczny? Prawdopodobnie w celu zaciemnienia. :-)
Icode4food

Dlaczego? Ponadto wszystko jest przydatne, jeśli można znaleźć tylko okoliczności, które tego wymagają. To prawda, że ​​ten jest rzadziej wymagany niż wiele innych, ale zdarzają się chwile, niewiele, a nawet daleko, chociaż może to być dokładnie narzędzie do pracy.
tymczasowego

Odpowiedzi:


440

Kolejność operacji powoduje (0 < 5 < 3)interpretację w javascript, ((0 < 5) < 3)która tworzy(true < 3) a wartość true jest liczona jako 1, co powoduje, że zwraca wartość true.

To jest również powód (0 < 5 < 1) zwraca false, (0 < 5)zwraca true, co jest interpretowane jako 1, w wyniku (1 < 1).


158
A ponieważ JavaScript NIE jest Pythonem. :-)
rsenna

1
Odpowiedziałeś podczas edytowania mojego pytania, aby dodać if(0 < 5 < 1) == false. Wszystko jest teraz jasne, dzięki :)
punkrockbuddyholly

28
Dokładnie, Python jest jedynym znanym mi językiem, który traktuje tę składnię ((0 < 5) && (5 < 3)), ponieważ są prawdopodobnie inne, ale ich nie znam.
Alan Geleynse

18
@Alan: Mathematica to kolejny przykład.
Joren

2
IMHO JavaScript powinien podnieść TypeError podczas próby porównania wartości logicznej z liczbą, ponieważ nie ma to sensu.
Michał Perłakowski

63

Domyślam się, ponieważ 0 < 5jest to prawda i true < 3zostaje rzucona na 1 < 3to, co jest prawdziwe.


7
Tutaj nie ma castingu. Rzutowanie to operator, którego programista używa do jawnego sprawdzenia typu. Jest to domniemana konwersja z wartości logicznej na liczbę całkowitą.
erickson,

4
@erickson, naprawdę ... czy NIESAMOWO potrzebujemy być tutaj związanym z semantyką?
CaffGeek,

2
Nie martw się o Erickson. Również niewłaściwie używam słowa semantyczna. :)
Mateen Ulhaq,

9
W każdym razie poprawnym terminem jest przymus . I tak, Erickson częściowo się myli ze swoją absolutną pewnością. Przymus jest w każdym razie rodzajem obsady również wtedy, gdy zwykle (ale jest to tylko konwencja) używasz słowa „obsada”, aby wyrazić konwersje typu jawnego. Konwersja typu == Rzutowanie typu.
Jack

1
Sofiści przez cały czas ... Odpowiedź i tak jest „lakoniczna”;)
Arman McHitarian

21

prawdopodobnie dlatego, że truezakłada się, jak 1tak

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


10

Jeśli chodzi o twoje pytanie, czy to dziwactwo jest kiedykolwiek przydatne: przypuszczam, że może być jakiś przypadek, w którym byłby użyteczny (jeśli szukasz skondensowanego kodu), ale poleganie na nim (najprawdopodobniej) poważnie zmniejszy zrozumiałość twojego kodu.

To trochę jak użycie post / wstępnej inkrementacji / dekrementacji jako części większych wyrażeń. Czy potrafisz określić, jaki jest wynik tego kodu?

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

Uwaga: dzięki temu kodowi możesz czasem uzyskać różne wyniki w zależności od języka i kompilatora.

Dobrym pomysłem jest ułatwienie życia tobie i następnemu facetowi, który przeczyta Twój kod. Wyraźnie zapisz, co naprawdę chcesz, aby się stało, zamiast opierać się na efektach ubocznych, takich jak niejawna konwersja booleanów.


Z ciekawości jest result18 lat?
punkrockbuddyholly

5
@MrMisterMan: Nie jestem pewien co do Javascript, ale w Javie i C # ocena jest gwarantowana od lewej do prawej, a wynik to rzeczywiście 18. W niektórych językach, takich jak C i C ++, nie ma gwarancji, że będzie to oceniano od lewej do prawej, a wyniki mogą być różne w zależności od optymalizacji dodanych przez kompilator.
Zach Johnson

9

Odpowiedź na drugą część pytania: „czy to dziwactwo jest kiedykolwiek przydatne?” jest być może nie, jak zauważono w poprzedniej odpowiedzi, jeśli rzeczywiście jest to dziwactwo języka (JavaScript), że prawda jest przypisana do 1, ale że programista nie widzi ogólnie 1 i prawda (i 0 i fałsz) jako ta sama rzecz.

Jeśli jednak masz model mentalny, w którym 1 jest prawdą, a 0 jest fałszem, prowadzi to do różnego rodzaju fajnych technik boolowskich, które są niezwykle przydatne, potężne i bezpośrednie. Na przykład możesz zwiększyć licznik bezpośrednio z wynikiem A> 100, co zwiększy licznik, jeśli A jest większe niż 100. Ta technika może być postrzegana jako dziwactwo lub sztuczka w Javie, ale w tablicy lub języku funkcjonalnym może być idiomatyczny.

Klasycznym przykładem w APL w języku tablicowym byłoby policzenie liczby elementów w tablicy, które są (powiedzmy) większe niż 100:

+/A>100

Gdzie, jeśli A jest tablicą 5 elementów 107 22 256 110 3, to:

A>100

daje 5-elementową tablicę boolowską:

1 0 1 1 0

i sumując ten wynik boolowski:

+/1 0 1 1 0

daje ostateczną odpowiedź:

3)

To pytanie jest doskonałym przykładem tego, gdzie ta technika byłaby bardzo przydatna, szczególnie jeśli problem jest uogólniony w celu ustalenia, czy n spośród m wartości logicznych jest prawdziwe.

Sprawdź, czy co najmniej dwa z trzech boolanów są prawdziwe


7

To łatwe.

(0 < 5 < 3)

Zacznij od lewej do prawej, aby ocenić pierwsze 0 <5. Czy to prawda? Tak. Ponieważ PRAWDA = 1, ocenia 1 <3. Ponieważ 1 jest mniejsze niż 3, więc to prawda.

Teraz z tym

 (0 < 5 < 1)

Czy 0 jest mniejsze niż 5? Tak. Więc uczyń to PRAWDĄ, co oznacza również 1. Teraz mając to na uwadze, ocenia na (1 <1). Czy 1 jest mniejsze niż 1? Nie, dlatego to nieprawda. To musi być równe.


4

czy ocenia 0 <5, co zwróci 1 dla prawdy, gdy 1 <3, co jest prawdą?

C # chcę pozwolić ci to zrobić „Operator” <”nie może być stosowany do operandów typu„ bool ”i„ int ””


Czasami brakuje mi surowości C # w dynamicznych językach.
Arman McHitarian

4

Wpadłem na to jakiś czas temu w Obj-C i bardzo mnie to zdziwiło. Otrzymałem pożądane wyniki, robiąc coś takiego:

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

Który oczywiście jest fałszywy, więc nie dostaniesz tego „prawdziwego” alarmu. Cieszę się, że to przeczytałem, teraz wiem dlaczego.


4

Oprócz Pythona CoffeeScript jest innym językiem, który obsługuje porównania łańcuchowe, dlatego 3 < x < 10zostałby przekonwertowany na (3 < x && x < 10)JS waniliowy



1

Logiczny operand, gdy jest obsługiwany przez operator matematyczny, zwraca liczbę. aby to sprawdzić, robimy

true + 1  which gives you 2.

Tak więc 0 < 5zwrócona wartość logiczna (prawda) operowana operatorem matematycznym (<) zwróci liczbę. Czyli sprowadza się do 1 <3, co zwracatrue


1

ponieważ 0 jest mniejsze niż 5, to zwraca true, a domyślnie true jest cokolwiek, w tym i może być ocenione na 1, który wciąż jest mniejszy niż 3, co ponownie zwraca true


0

spróbuj sformułować swoje wyniki jako Number ()

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

lub spróbuj tego:

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

Przejrzałem to, ponieważ otrzymywałem (3 >= 20) //returning truei domyślam się, że javascript próbował sprawdzić 3jako wartość logiczną, ponieważ otrzymywałem tę wartość z elm.getAttribute();funkcji, która console.log();była drukowana w postaci ciągu.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.