Чому 0.-5 оцінюється як -5?


84

Припустимо, я пишу 0.5як 0.-5несподівано, але він все одно може працювати. Що робить 0.in 0.-5, щоб він все ще міг працювати і оцінюється до -5?

Я також спробував , alert(0.-5+1)який друкує -4, робить JavaScript ігнорувати 0.в 0.-5?


55
0.це як 0.0. Або просто 0.
Ry-

61
Що змушує вас думати, що 0.-5це "несподіваний шлях"?
Ніко Хаасе

15
@NicoHaase: Я майже впевнений, що OP використовував "несподіваний спосіб", щоб означати "я не мав наміру / очікував написати це, але якось так і зробив".
Філіп Мілованович

15
Це працює також у багатьох інших мовах (наприклад, Python). Мені особисто це зовсім не подобається. Я волів би 0.-5мати синтаксичну помилку і не дозволяти плаваючі літерали з кінцевим періодом, але змусити людей писати .0в кінці.
Джакомо Альзетта

9
Це особливо погано, тому що дозволяючи закінчувати числа, .заважає писати щось на кшталт 123.toString(16)(Загальна хитрість полягає у використанні 123..toString(16), що є насправді (123.).toString(16))
12Me21

Відповіді:


191

Кінцеві цифри після a .необов’язкові:

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

Тому

0.-5

оцінює до

0 - 5

що справедливо -5. Так само,

0.-5+1

є

0 - 5 + 1

який є

-5 + 1

або -4.


16
Провідні цифри також не є обов’язковими, тому .0-5 також є дійсним
айснак

48

0.-5може бути успішно проаналізований як 0.[1] , -і 5. Нижче наведено дерево абстрактного синтаксису для виразу, згенерованого провідником AST:

Дерево синтаксичного аналізу, створене провідником AST

Це (несподіваним чином) є дійсним JavaScript і обчислюється на -5.


[1] Відповідно до граматики для числових літералів десяткові цифри та експоненти не є обов’язковими:

NumericLiteral ::
  DecimalLiteral
  [...]

DecimalLiteral ::
  ДесятичнийцілийЛітерал. DecimalDigits opt ExponentPart opt


як ви отримали AST?
Κωλζαρ

8
Зайдіть на astexplorer.net , оберіть мову та синтаксичний аналізатор, вставте код, оберіть вихід JSON (або просто зробіть знімок екрана).
Салман

39

У JS ви можете виразити число необов'язковою десятковою комою.

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

А на коментар Tvde1 можна застосувати будь-який метод Number.

5..toString()

Цей синтаксис дозволить запустити функції Number без дужок.

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

Перегляньте це запитання, щоб з’ясувати, чому.


4
Можна навіть зробити 5..toString().
Tvde1,

2
Якщо насправді, вам потрібно зробити 5..toString (), щоб викликати метод, інакше, ви повинні використовувати дужки: (5) .toString ()
jo_va

3
@PeterMortensen Ruby, наприклад. Також АЛГОЛ 68. У Common Lisp, як не дивно, 1.0це плаваюча точка, але 1.є цілим числом.
Снефтель

2
@FlorianF Ви б цього не зробили, але це не означає, що синтаксичний аналізатор повинен бути спеціально оброблений, щоб відхилити його. floats мають методи, і 5.є a float.
Чепнер

2
@MasonWheeler Це, звичайно, не той випадок, коли будь-яка інша мова, яка (1).toMethod()є законною, забороняє (1.)правильно аналізувати. Найбільш традиційний підхід до синтаксичного аналізу (жадібна лексика лексем, включаючи літерали, а потім синтаксичний аналіз) створює поведінку Javascript.
Снефтель

7

Я б подумав, що справжня відповідь полягає не в десятковій крапці, а в знаку мінус: хіба це не буде інтерпретовано як оператор, якщо перед ним стоїть щось, схоже на число?


1
Тоді, принаймні в певній точці зору, все-таки мова йде про десяткову крапку, що інтерпретується як частина числового літералу, інакше те, що передувало знаку мінус, не «виглядає як число».
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." або '0' те саме в JavaScript, оскільки тип унікальний для чисел, який називається Number. Оператор мінус знаходиться між числами, намагайтеся завжди перетворювати передане в число. У Python різний перший - це Float, а другий - Integer, оскільки він має кілька типів.


Ця проблема не пов’язана з типами; це пов’язано лише із синтаксисом.
user4642212
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.