+0 и -0 одинаковы? - PullRequest
       58

+0 и -0 одинаковы?

148 голосов
/ 28 августа 2011

При чтении спецификации ECMAScript 5.1 * различаются 1002 *, +0 и -0.

Почему тогда +0 === -0 оценивается как true?

Ответы [ 9 ]

168 голосов
/ 28 августа 2011

JavaScript использует стандарт IEEE 754 для представления чисел.От Википедия :

Ноль со знаком - ноль со связанным знаком.В обычной арифметике −0 = +0 = 0. Однако в вычислениях некоторые числовые представления допускают существование двух нулей, часто обозначаемых −0 (отрицательный ноль) и + 0 (положительный ноль) .Это происходит в некоторых представлениях чисел со знаком для целых чисел и в большинстве представлений чисел с плавающей точкой.Число 0 обычно кодируется как +0, но может быть представлено либо +0, либо -0.

Стандарт IEEE 754 для арифметики с плавающей запятой (в настоящее время используется большинством компьютеров и языков программирования, которые поддерживают числа с плавающей запятой) требует +0 и −0.Нули можно рассматривать как вариант расширенной строки действительных чисел, такой что 1 / −0 = −∞ и 1 / + 0 = + ∞, деление на ноль не определено только для ± 0 / ± 0 и ± ∞ / ± ∞.

В статье содержится дополнительная информация о различных представлениях.

Таким образом, по этой причине технически следует различать оба ноля.

Однако +0 === -0 оценивается как true.Почему это (...)?

Это поведение явно определено в разделе 11.9.6 , Алгоритме сравнения строгого равенства (выделение частично мое):

Сравнение x === y, где x и y - значения, выдает true или false .Такое сравнение выполняется следующим образом:

(...)

  • Если тип (x) является числом, то

    1. Еслиx - NaN, верните false.
    2. Если y - NaN, верните false.
    3. Если x - это то же числовое значение, что и y, верните true.
    4. Еслиx равен +0, а y равен −0, возвращает true.
    5. Если x равен −0, а y равен +0, возвращает true.
    6. Возвращает false.

(...)

(То же самое относится к +0 == -0 между прочим)

Логично рассматривать +0 и -0 как равные.В противном случае мы должны были бы принять это во внимание в нашем коде, и я лично не хочу этого делать;)


Примечание:

ES2015вводит новый метод сравнения, Object.is.Object.is явно различает -0 и +0:

Object.is(-0, +0); // false
15 голосов
/ 01 сентября 2016

Я добавлю это как ответ, потому что я пропустил комментарий @ user113716.

Вы можете проверить -0, выполнив это:

function isMinusZero(value) {
  return 1/value === -Infinity;
}

isMinusZero(0); // false
isMinusZero(-0); // true
3 голосов
/ 28 августа 2011

В стандарте IEEE 754 , используемом для представления типа числа в JavaScript, знак представлен битом (1 означает отрицательное число).

В результате для каждого представимого числа существует как отрицательное, так и положительное значение, включая 0.

Вот почему существуют -0 и +0.

2 голосов
/ 26 сентября 2016

Мы можем использовать Object.is, чтобы различать +0 и -0, и еще одну вещь, NaN==NaN.

Object.is(+0,-0) //false

Object.is(NaN,NaN) //true
2 голосов
/ 20 августа 2015

Отвечая на оригинальное название Are +0 and -0 the same?:

brainslugs83 (в комментариях к ответу Spudley) указывается на важный случай, когда +0 и -0 в JS не совпадают - реализованокак функция:

var sign = function(x) {
    return 1 / x === 1 / Math.abs(x);
}

Это, кроме стандартных Math.sign, вернет правильный знак +0 и -0.

2 голосов
/ 28 августа 2011

Есть два возможных значения (битовые представления) для 0. Это не уникально. Особенно в числах с плавающей точкой это может произойти. Это потому, что числа с плавающей запятой на самом деле хранятся в виде формулы.

Целые числа также могут храниться разными способами. Вы можете иметь числовое значение с дополнительным знаковым битом, поэтому в 16-битном пространстве вы можете хранить 15-битное целочисленное значение и знаковый бит. В этом представлении значения 1000 (hex) и 0000 оба равны 0, но одно из них равно +0, а другое - -0.

Этого можно избежать, вычитая 1 из целочисленного значения, чтобы оно варьировалось от -1 до -2 ^ 16, но это было бы неудобно.

Более распространенный подход - хранить целые числа в «двух дополнениях», но, очевидно, ECMAscript предпочел не делать этого. В этом методе числа в диапазоне от 0000 до 7FFF положительны. Отрицательные числа начинаются с FFFF (-1) до 8000.

Конечно, те же правила применимы и к большим целым числам, но я не хочу, чтобы мой F изнашивался. ;)

1 голос
/ 04 ноября 2018

Я только что натолкнулся на пример, в котором +0 и -0 ведут себя совершенно по-разному:

Math.atan2(0, 0);  //returns 0
Math.atan2(0, -0); //returns Pi

Будьте осторожны: даже при использовании Math.round с отрицательным числом, таким как -0.0001, оно действительно будет-0 и может испортить некоторые последующие вычисления, как показано выше.

Быстрый и грязный способ исправить это - выполнить что-то вроде:

if (x==0) x=0;

или просто:

x+=0;

Преобразует число в +0, если оно было -0.

1 голос
/ 26 января 2018

Я бы обвинил его в методе сравнения строгого равенства ('===').Смотрите раздел 4d enter image description here

см. 7.2.13 Сравнение строгого равенства в спецификации

0 голосов
/ 28 августа 2011

В Википедии есть хорошая статья, чтобы объяснить это явление: http://en.wikipedia.org/wiki/Signed_zero

Вкратце, оба значения +0 и -0 определены в спецификации IEEE с плавающей запятой. Они оба технически отличаются от 0 без знака, который является целым числом, но на практике все они оцениваются как ноль, поэтому различие можно игнорировать для всех практических целей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...