"===" также ненадежен

внешний интерфейс программист JavaScript Underscore.js

Написано 8 мая 2015 г., последняя редакция 26 мая 2015 г., может быть устаревшей, обращайтесь к ней с осторожностью.

оригинальный

С древних времен js был замечательным, и на уровне языка есть много ям. Потом еще одно отверстие.

Когда javascript судит, равны ли два значения, есть два способа== а также===. Я не буду много говорить о разнице между ними, это можно найти в любой книге по js, короче, в целом мы имеем такой вывод:==Это избавляет от проблем, но результат сбивает с толку. Во многих случаях это почти псевдонаучно. Его не рекомендуется использовать. Многие люди считают его зверем и избегают его.===Очень строгий и должен использоваться в большинстве случаев. Я согласен с этим выводом и стараюсь делать это по мере возможности. Однако, как своенравный язык, javascript так забавен без пощечин. Так что давайте веселиться вместе===Бар.

играть плохо===просто используйте 0. Это верно, это число 0. В JavaScript Numbers участвуют в операциях в виде номеров с плавающей точкой, а также правила их кодированияIEEE_754стандарт(0.2+0.1Не равно 0,3 эта проблема виновата! ). Дело не в этом стандарте, дело в том, что в соответствии с этим стандартом цифровое кодирование будет иметь знаковый бит для обозначения положительного и отрицательного, поэтому для любого числа он либо положительный, либо отрицательный. Итак, вопрос в том, что насчет 0? Ответ 0 также положительный и отрицательный. Обычно то, что мы видим, означает, что 0 равно +0, но в javascript также существует -0. В реальной работе в некоторых сценариях результат расчета будет иметь разницу между +0 и -0; когда в расчете также участвуют +0 и -0, это может привести к другим результатам. Но интуитивно очевидно, что +0 и -0 должны быть равны, поэтому javascript хочет устранить эту разницу на уровне языка, поэтому:

QQ20150508115353

Выглядит разумно, хотя и немного странно. Но посмотрите еще раз на эту операцию:

QQ20150508115038

Это ненаучно.Четко определено, что значение точно такое же.После выполнения одной и той же операции результаты не будут равными. Для разработчиков мы не можем доверять ни в одном сценарии===, у него также есть ненадежные времена.

Разобраться с этой «ненаучной» ситуацией тоже очень просто:

function isEqual(a, b){
    if (a !== b) return false;
    return a !== 0 || 1 / a === 1 / b;
}

Добавлено 14 мая 2015 г.:

Чтобы подчеркнуть смысл этой статьи, я никогда не хотел ставить под сомнение проблему неравной положительной и отрицательной Бесконечности.Основные моменты, которыми я хочу поделиться, таковы:В js +0 === -0, но они не совсем равны.


Добавлено 26 мая 2015 г.:

Первый ответ на комментарий длиннее текста... давайте сосредоточимся на его сортировке.

О стандарте IEEE_754

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

Я говорю, что проблема отрицательного 0 несерьезна, потому что у него мало сценариев использования и низкая вероятность багов. Говоря о несерьезных, должны быть серьезные проблемы, то есть проблема точности с плавающей запятой.Числовое значение является точным и непрерывным, а числовое кодирование дискретным и часто неточным. В конце концов, будь то 32-битный или 64-битный, числа с плавающей запятой, которые могут быть представлены, ограничены. От 0,1, 0,2 до 0,9 действительно точно можно выразить только 0,5, а остальные числа приблизительны. Вы можете попробовать это сами, независимо от js, java или c++, арифметика с плавающей запятой никогда не будет надежной, например0.2+0.1Не равно 0,3. Если у вас есть опыт программирования на C++ или Java, вы могли столкнуться с каким-то странным кодом для работы со сравнениями с плавающей запятой, например, с определением точности 0,002f (гипотетически), еслиabs(floatA - floatB) < 0.002f, они считаются равными. Очень античеловечно, но никак. Являются ли языки программирования неправильными? Нет, но реальность состоит в том, чтобы идти на компромисс.

О минус 0

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

Является ли отрицательный 0 обычным явлением?

Позвольте мне начать с того, что отрицательный 0 встречается редко, но ни в коем случае не невозможно, как все думают. Фактически, -0 может появиться в некоторых распространенных и простых сценариях. НапримерMath.ceil(-0.1),Math.round(-0.1); и режеMath.atan2(-1, Infinity) Ждать. Существует относительно больше операций, которые генерируют разные результаты вычислений из положительного и отрицательного 0, например, обратная операция примера в статье.

Использованная литература:

=== работа с javascript

Обычно === в js означает, что тип и значение точно равны. Говорят, что это нормально, но должны же быть и обратные примеры. Многие люди, знакомые с js, знают такой пункт знаний,NaN !== NaN. Поэтому мы часто видим такой код:

function isNaN (num){
    return num !== num;
}

Это результат того, что языки программирования манипулируют операторами для интуитивного понимания. То же самое верно для +0 и -0, они не кодируются по-разному, но определяются как равные.

Для двух вышеуказанных пунктов EmacScript 6 добавилObject.isметод обработки:

Object.defineProperty(Object, 'is', {
    value: function(x, y) {
        if (x === y) {
        // 0 === -0, but they are not identical
        return x !== 0 || 1 / x === 1 / y;
        }

        // NaN !== NaN, but they are identical.
        // NaNs are the only non-reflexive value, i.e., if x !== x,
        // then x is a NaN.
        // isNaN is broken: it converts its argument to number, so
        // isNaN("foo") => true
        return x !== x && y !== y;
    },
    configurable: true,
    enumerable: false,
    writable: true
});

Использованная литература:

Для проблемы отрицательного 0 EmacScript 5 также добавилisNegative0обрабатывать -0.

Использованная литература:

Мало того, некоторые библиотеки инструментов также добавили подобную обработку, например, символы подчеркивания.isEqualметод.

So...

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