Почему Math.pow(-0, -7) === -Infinity?

Существует ли обоснование для Math.pow(-0, x) для определения бесконечности для всех отрицательных x, за исключением нечетных, когда это -Infinity? Я имею в виду:

Math.pow(-0, -6);          // Infinity
Math.pow(-0, -7);          // -Infinity
Math.pow(-0, -7.33);       // Infinity
Math.pow(-0, -Infinity);   // Infinity

Fiddle

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

Такое поведение математически не имеет смысла, и я не вижу в нем практического использования или технического удобства, поэтому я подозреваю, что спецификация должна опираться на причины, связанные с историей/совместимостью. Любые идеи?

Ответ 1

Я считаю, что это для согласованности с полномочиями других отрицательных чисел. Когда вы поднимаете отрицательное число до равномерной мощности, вы всегда получаете положительный результат. Но когда вы поднимаете отрицательное число до нечетной мощности, вы получаете отрицательный результат. Приведение нуля к отрицательной мощности всегда приводит к бесконечности (поскольку она эквивалентна делению на ноль); в случае отрицательного нуля знак чередуется, как и другие отрицательные числа.

Ответ 2

Смотрите, Math.pow(x, -n) действительно то же самое, что и 1/Math.pow(x, n). Вы совершенно правильно заметили, что нечетная мощность отрицательного числа является отрицательной. И когда вы делаете 1/negative, это все равно negative, очевидно.

Но я думаю, что ключевая часть вопроса такова:

в то время как -0 действительно число, если вы открываете свой ум, это не отрицательный.

Ну, в JavaScript он фактически рассматривается как отрицательное значение во многих аспектах - конечно, прямое сравнение с 0. Например, Math.abs(-0) возвращает 0, а не -0, а операции по модулю сохраняют знак:

0 % 42; // 0
-0 % 42; // -0

Один трюк выделяется из толпы: если вы разделите любое положительное число на 0, вы получите Infinity:

console.log(1/0);                // Infinity
console.log(Number.MIN_VALUE/0); // still Infinity

... но если вы разделите то же число на -0, угадайте, что вы получите -Infinity:

console.log(Number.MIN_VALUE/-0); // -Infinity

Этот трюк обычно используется, когда вам просто нужно различать 0 и -0 - как прямое сравнение (0 === -0) оценивается как true.


Теперь, почему язык должен иметь отрицательный аналог n evil twin нормального нуля? Как сказал @Barmar, консистенция (скорее всего) является основной причиной здесь. Например, существует известное правило в JS: когда вы выполняете операцию по модулю, знак результата является знаком первого операнда. Таким образом, оба этих -5 % 2 и -5 % -2 приводят его к -1, тогда как 5 % 2 и 5 % -2 приводят к 1.

Это было немного неожиданно для меня, когда я это обнаружил, но это же правило применяется, когда первый операнд фактически делится на второй:

 5 % 5;   // 0
-5 % 5;   // -0
-5 % -5;  // -0
 5 % -5;  // 0

... так что правило все еще нетронутым. Однако еще более важной причиной является способность последовательно изменять операцию: если a / b => c, то a / c должно быть равно b. В JS это верно даже тогда, когда b является Infinity или -Infinity, так как вы получаете разные c (0 в первом, -0 в последнем) и сможете "восстановить" делитель.

Ответ 3

Предполагается, что эта реализация Java script использует следующую логику:

Для четных степеней:

    Math.pow(-0, -6) ==       // a**(-b) == 1.0/a**b
    1.0 / Math.pow(-0, 6) ==  // (-a)**(2*b) == a**(2*b)
    1.0 / Math.pow(0, 6) ==   // 0**b == 0
    1.0 / 0.0 == 
    Infinity

Для нечетных степеней:

    Math.pow(-0, -7) ==       // a**(-b) == 1.0/a**b
    1.0 / Math.pow(-0, 7) ==  // (-a)**(2b+1) == -a**(2b+1) 
   -1.0 / Math.pow(0, 7) ==   // 0**b == 0
   -1.0 / 0.0 == 
   -Infinity

Ответ 4

Из документации нам сообщается следующее:

Если первый аргумент отрицательный ноль, а второй аргумент - отрицательное конечное нечетное целое число, или первый аргумент - отрицательная бесконечность, а второй аргумент - положительное конечное нечетное целое число, то результат отрицательной бесконечности.

Он выглядит довольно стандартным для разных языков, таких как Javascript и Java. Сами методы могут различаться, но, как правило, они вычисляются практически одинаково.

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

РЕДАКТИРОВАТЬ: Как показано выше, ссылка для Java, и некоторые люди не верят мне, что она довольно стандартная, ознакомьтесь с этим Javascript Reference, Обратите внимание, что он практически идентичен тому, что указано выше. Это связано с тем, что функция Math.pow(), будь то на Java, Javascript, С++ или на другом языке, работает точно так же внутренне. Ваш компьютер предназначен для обработки этих команд таким же образом, а язык/компилятор не меняет этого. Вот почему они фактически одинаковы.

Ответ 5

Вероятно, это связано с тем, как номера хранятся в JavaScript. Хотя вы правильно говорите, что это не имеет никакого математического смысла, к сожалению, аппаратное и программное обеспечение действительно может делать только то, что им явно сказано.

Сначала рассмотрим базовую математику.

x ^ -y можно выразить как (1/x) ^ y

(- x) ^ y, где y нечетно, дает отрицательный результат

(- x) ^ y, где y четно, дает положительный результат

Далее, давайте учтем некоторые основные ограничения:

lim (x) при x- > inf = inf

lim (1/x) при x- > inf = 0

lim (-x) при x- > inf = -inf

lim (1/(- x)) при x- > inf = 0

lim (x) при x- > 0 = 0

lim (1/x) при x- > 0 = inf

lim (-x) при x- > 0 = -0

lim (1/(- x)) при x- > 0 = -inf

Самый интересный из них - последний.

Самая важная часть информации состоит в том, что JavaScript хранит числа как подписанное число (ссылка).

Значение, когда это оценивается (хотя для нас не имеет смысла, что 0 может быть отрицательным), бит знака устанавливается для вашего нуля.

Когда вычисляется значение pow, у него, вероятно, есть ярлык, чтобы увидеть, что x/0 = inf. Когда функция возвращается, она, вероятно, вычисляет знаковый бит (на основе математики сверху), затем (используя вышеприведенные лимиты) устанавливает номер в inf.

Короче говоря: JavaScript хранит номера в виде подписанных удвоений. Язык не был написан для дифференциации между -0 и +0, а мультипликативные функции обрабатывали знак от -0 и +0, как и любое другое число.

Надеюсь, что это поможет.

Ответ 6

Я не согласен с вашим утверждением: "пока -0 действительно число, если вы открываете свой разум, это не отрицательный".

Это имеет смысл математически, если вы принимаете -0 эквивалентом -1/Бесконечность. На самом деле, это не так уж и много, чтобы смотреть на это с этой точки зрения. И это отрицательное число и может быть перенесено как отрицательное число для этой операции .pow(). Когда вы комбинируете это с тем, что Math.pow(x, -y) равно 1/Math.pow(x, y), я думаю, что имеет смысл, что Math.pow(-0, -7) === -Infinity.