Читання через ECMAScript 5.1 специфікації , +0і -0відрізняються.
Чому тоді +0 === -0оцінюють true?
Object.isрозрізняти +0 і -0
Читання через ECMAScript 5.1 специфікації , +0і -0відрізняються.
Чому тоді +0 === -0оцінюють true?
Object.isрозрізняти +0 і -0
Відповіді:
JavaScript використовує стандарт IEEE 754 для представлення чисел. З Вікіпедії :
Підписаний нуль дорівнює нулю з пов’язаним знаком. У звичайній арифметиці −0 = +0 = 0. Однак у обчислювальних технологіях деякі числові подання дозволяють існувати дві нулі, часто позначаються −0 (від'ємний нуль) та +0 (додатний нуль) . Це трапляється в деяких представленнях підписаних чисел для цілих чисел, а також у більшості подань чисел з плаваючою комою. Число 0 зазвичай кодується як +0, але може бути представлене або +0, або -0.
Стандарт IEEE 754 для арифметики з плаваючою комою (в даний час використовується більшістю комп'ютерів і мов програмування, які підтримують числа з плаваючою комою) вимагає як +0, так і −0. Нулі можна розглядати як варіант розширеного прямої лінійки чисел таким, що 1 / −0 = −∞ та 1 / + 0 = + ∞, ділення на нуль не визначено лише для ± 0 / ± 0 та ± ∞ / ± ∞ .
Стаття містить додаткову інформацію про різні уявлення.
Тому це технічно обидві нулі мають розрізняти технічно.
Однак
+0 === -0оцінюється як вірно. Чому так (...) ?
Така поведінка явно визначено в розділі 11.9.6 , то суворе рівність алгоритм порівняння (курсив частково мій):
Порівняння
x === y, деxіyє значеннями, дає істинне або хибне . Таке порівняння проводиться так:(...)
Якщо Тип (x) - Число, то
- Якщо x NaN, поверніть false.
- Якщо y - NaN, поверніть хибне.
- Якщо x - те саме значення числа, що і y, поверніть true.
- Якщо x дорівнює +0, а y - 0, поверніть true.
- Якщо x дорівнює -0, а y +0, поверніть true.
- Повернути помилково.
(...)
(Те ж саме стосується і +0 == -0BTW.)
Здається, логічно ставитись +0і -0як до рівних. Інакше нам доведеться це враховувати у своєму коді, і я особисто цього не хочу робити;)
Примітка:
ES2015 вводить новий метод порівняння, Object.is. Object.isчітке розходження між -0і +0:
Object.is(-0, +0); // false
1/0 === Infinity; // trueі 1/-0 === -Infinity; // true.
1 === 1і +0 === -0але 1/+0 !== 1/-0. Як дивно!
+0 !== -0;) Це справді може створити проблеми.
0 !== +0/ 0 !== -0, що теж створило б проблеми!
Я додам це як відповідь, тому що я не помітив коментаря @ user113716.
Ви можете протестувати на -0, зробивши це:
function isMinusZero(value) {
return 1/value === -Infinity;
}
isMinusZero(0); // false
isMinusZero(-0); // true
e±308, що ваше число може бути представлене лише в денормалізованій формі, а різні реалізації мають різні думки щодо того, де їх взагалі підтримувати чи ні. Справа в тому, що на деяких машинах у деяких режимах з плаваючою точкою ваше число представлено як, -0а на інших - денормоване число 0.000000000000001e-308. Такі поплавки, такі веселі
Я щойно натрапив на приклад, коли +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.
У стандарті IEEE 754, який використовується для представлення типу Числа в JavaScript, знак представлений бітом (a 1 означає негативне число).
В результаті існує як негативне, так і позитивне значення для кожного репрезентативного числа, в тому числі 0.
Ось чому обидва -0і +0існують.
Відповідь на оригінальну назву 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.
Можливі два значення (бітові подання) для 0. Це не унікально. Особливо в числах з плаваючою комою це може статися. Це тому, що числа з плаваючою комою насправді зберігаються як своєрідна формула.
Цілі особи також можуть зберігатися окремо. Ви можете мати числове значення з додатковим бітом знаків, тому в 16-бітовому просторі ви можете зберігати 15-бітове ціле значення і біт знаків. У цьому поданні значення 1000 (hex) та 0000 обидва - 0, але один з них +0, а інший -0.
Цього можна уникнути, віднімаючи 1 від цілого числа, так що воно становило від -1 до -2 ^ 16, але це було б незручно.
Більш поширений підхід - зберігання цілих чисел у "двох доповненнях", але, очевидно, ECMAscript вирішив не робити. У цьому методі цифри варіюються від 0000 до 7FFF додатними. Негативні цифри починаються від FFFF (-1) до 8000.
Звичайно, ті ж правила застосовуються і до більших цілих чисел, але я не хочу, щоб мій F зношувався. ;)
+0 === -0це трохи дивним. Тому що тепер у нас є 1 === 1і +0 === -0але 1/+0 !== 1/-0...
+0 === -0незважаючи на те, що представлення двох бітів відрізняються.
Я б звинувачував це в методі суворого порівняння рівності ('==='). Подивіться на розділ 4d

див. 7.2.13 Суворе порівняння рівності у специфікації
У Вікіпедії є гарна стаття для пояснення цього явища: http://en.wikipedia.org/wiki/Signed_zero
Якщо коротко, то і +0 і -0 визначені в специфікаціях IEEE з плаваючою точкою. Обидва вони технічно відрізняються від 0 без знака, що є цілим числом, але на практиці всі вони оцінюються до нуля, тому розрізнення можна ігнорувати для всіх практичних цілей.