Почему 0.-5 оценивается как -5?

85

Допустим, я пишу 0.5как-то 0.-5неожиданным образом, но все равно может работать. Что 0.в 0.-5сделать так , чтобы он все еще может работать и оценивает до -5?

Я также попробовал , alert(0.-5+1)который печатает -4, делает JavaScript игнорировать 0.в 0.-5?

ocomfd
источник
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.

CertainPerformance
источник
17
Начальные цифры также необязательны, поэтому .0-5 также действительны
icenac
48

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

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

Это (неожиданным образом) правильный JavaScript и оценивается как -5.


[1] Согласно грамматике числовых литералов, десятичные цифры и экспоненты являются необязательными:

NumericLiteral ::
  DecimalLiteral
  [...]

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

Салман А
источник
как вы извлекли AST?
Κωλζαρ
8
Зайдите в astexplorer.net , выберите язык и парсер, вставьте код, выберите вывод JSON (или просто сделайте снимок экрана).
Salman A
39

В JS вы можете выразить число с помощью необязательной десятичной точки.

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

И, что касается комментария Tvde1, можно применить любой числовой метод.

5..toString()

Этот синтаксис позволяет запускать числовые функции без скобок.

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.целое число.
Sneftel
2
@FlorianF Вы бы этого не сделали, но это не значит, что парсер должен иметь специальный корпус, чтобы его отклонить. floats имеют методы, а 5.это float.
chepner
2
@MasonWheeler Это, конечно, не тот случай, когда какой-либо другой язык, где (1).toMethod()это разрешено, запрещает (1.)анализ должным образом. Самый традиционный подход к синтаксическому анализу (жадное лексирование токенов, включая литералы, затем синтаксический анализ) приводит к поведению Javascript.
Sneftel
7

Я бы подумал, что настоящий ответ касается не десятичной точки, а знака минус: разве это не будет интерпретировано как оператор, если ему предшествует что-нибудь, похожее на число?

Sean_999
источник
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 все по-другому: первое - это число с плавающей запятой, а второе - целое число, потому что оно имеет несколько типов.

Κωλζαρ
источник
Эта проблема не связана с типами; это связано только с синтаксисом.
Себастьян Саймон