Dlaczego 0.-5 daje -5?

84

Załóżmy, że piszę 0.5jak 0.-5w nieoczekiwany sposób, ale może nadal działać. Czego 0.się 0.-5zrobić tak, że można go uruchomić i nadal ma wartość -5?

Próbowałem też, alert(0.-5+1)który drukuje -4, czy JavaScript ignoruje 0.w 0.-5?

ocomfd
źródło
55
0.jest jak 0.0. Albo po prostu 0.
Ry-
61
Dlaczego myślisz, że 0.-5to „nieoczekiwany sposób”?
Nico Haase,
15
@NicoHaase: Jestem prawie pewien, że OP użył „nieoczekiwanego sposobu” na oznaczenie „Nie zamierzałem / nie spodziewałem się tego napisać, ale jakoś to zrobiłem”.
Filip Milovanović
15
Działa to również w wielu innych językach (np. Python). Osobiście wcale mi się to nie podoba. Wolałbym raczej 0.-5być błędem składni i nie zezwalać na literały zmiennoprzecinkowe z końcową kropką, ale zmuszać ludzi do pisania .0na końcu.
Giacomo Alzetta
9
Jest to szczególnie złe, ponieważ zezwalanie na kończenie się liczbami .uniemożliwia napisanie czegoś w stylu 123.toString(16)( 123..toString(16)(123.).toString(16)
Typową

Odpowiedzi:

191

Cyfry końcowe po a .są opcjonalne:

console.log(0. === 0); // true

Więc

0.-5

ewaluuje do

0 - 5

co jest sprawiedliwe -5. Podobnie,

0.-5+1

jest

0 - 5 + 1

który jest

-5 + 1

lub -4.

CertainPerformance
źródło
16
Cyfry wiodące są również opcjonalne, więc .0-5 jest również ważne
icenac
48

0.-5może zostać pomyślnie przeanalizowany jako 0.[1] , -a 5. Poniżej znajduje się abstrakcyjne drzewo składni dla wyrażenia wygenerowanego przez eksploratora AST:

Drzewo analizy wygenerowane przez eksploratora AST

To (w nieoczekiwany sposób) jest poprawnym JavaScriptem i ma wartość -5.


[1] Zgodnie z gramatyką literałów numerycznych cyfry dziesiętne i części wykładników są opcjonalne:

NumericLiteral ::
  DecimalLiteral
  [...]

DecimalLiteral ::
  DecimalIntegerLiteral. DecimalDigits opt ExponentPart opt

Salman A
źródło
jak wyodrębniłeś AST?
Κωλζαρ
8
Wejdź na astexplorer.net , wybierz język i parser, wklej kod, wybierz wyjście JSON (lub po prostu zrób zrzut ekranu).
Salman A
39

W JS możesz wyrazić liczbę z opcjonalną kropką dziesiętną.

x = 5.;    //5
x = 5. + 6.   //11

Od komentarza Tvde1 można również zastosować dowolną metodę numeryczną.

5..toString()

Ta składnia pozwala nam uruchamiać funkcje Number bez nawiasów.

5.toString() //error
(5).toString() //good
5..toString() //good
5 .toString() // awesome

Zobacz to pytanie, aby dowiedzieć się, dlaczego.

Charlie
źródło
4
Możesz nawet to zrobić 5..toString().
Tvde1
2
W rzeczywistości musisz wykonać 5..toString (), aby wywołać metodę, w przeciwnym razie musisz użyć nawiasów: (5) .toString ()
jo_va
3
@PeterMortensen Ruby, na przykład. Również ALGOL 68. W Common Lisp, co dziwne, 1.0jest zmiennoprzecinkowe, ale 1.jest liczbą całkowitą.
Sneftel
2
@FlorianF Nie zrobiłbyś tego, ale to nie znaczy, że parser powinien mieć specjalną wielkość liter, aby go odrzucić. floats mają metody i 5.jest float.
chepner
2
@MasonWheeler Z pewnością nie jest tak, że jakikolwiek inny język, w którym (1).toMethod()jest to legalne, zabrania (1.)prawidłowego analizowania. Najbardziej tradycyjne podejście do analizowania (zachłanne leksowanie tokenów, w tym literałów, a następnie analizowanie) powoduje zachowanie JavaScript.
Sneftel
7

Myślę, że prawdziwa odpowiedź nie dotyczy przecinka, ale znaku minus: czy nie będzie to interpretowane jako operator, jeśli jest poprzedzone czymś, co wygląda jak liczba?

Sean_999
źródło
1
Wtedy, przynajmniej z jakiegoś punktu widzenia, nadal chodzi o to, aby przecinek dziesiętny był interpretowany jako część literału liczbowego, w przeciwnym razie to, co poprzedzało znak minus, nie „wyglądałoby jak liczba”.
Pac0
5

console.log(0. - 5)      // -5
console.log(0 - 5)       // -5
console.log('0.' - 5)    // -5
console.log('0' - 5)     // -5
console.log(0.-5 === -5) // true

„0” lub „0” oznacza to samo w JavaScript, ponieważ typ jest unikalny dla liczb, nazywany liczbą. Operator minus znajduje się między liczbami, staraj się zawsze konwertować to, co przekazujesz, na liczbę. W Pythonie jest inaczej, po pierwsze to Float, a po drugie Integer, ponieważ ma kilka typów.

Κωλζαρ
źródło
Ten problem nie jest związany z typami; jest to związane tylko ze składnią.
user4642212