Почему Math.pow(0, 0) === 1?

Мы все знаем, что 0 0 неопределен.

Но, javascript говорит, что:

Math.pow(0, 0) === 1 // true

и С++ говорит то же самое:

pow(0, 0) == 1 // true

Почему?

Я знаю, что:

>Math.pow(0.001, 0.001)
0.9931160484209338

Но почему Math.pow(0, 0) не выдает ошибок? Или, может быть, NaN будет лучше, чем 1.

Ответ 1

В С++ Результат pow (0, 0) результат в основном определяется реализацией, поскольку математически мы имеем противоречивую ситуацию, когда N^0 всегда должен быть 1, но 0^N всегда должен быть 0 для N > 0, поэтому у вас не должно быть математически ожиданий относительно результата этого. Это сообщение Wolfram Alpha содержит более подробные сведения.

Несмотря на то, что pow(0,0) результат 1 полезен для многих приложений, поскольку Обоснование для международных языков стандартного программирования-C указано в разделе, посвященном IEC 60559 арифметическая поддержка с плавающей запятой:

Как правило, C99 избегает результата NaN, где полезно числовое значение. [...] Результаты pow (∞, 0) и pow (0,0) равны 1, потому что есть приложения, которые могут использовать это определение. Например, если x (p) и y (p) - любые аналитические функции, которые становятся равными нулю при p = a, то pow (x, y), равная exp (y * log (x)), приближается к 1 по мере приближения p а.

Обновить С++

Как правильно указывали leemes, я первоначально был связан со ссылкой на сложную версию pow, в то время как некомплексная версия утверждает, что это ошибка домена черновик стандарта С++ возвращается к проекту стандарта C и как C99, так и C11 в разделе 7.12.7.4 В параграфах функций pow сказано: (внимание мое):

[...] Ошибка домена может иметь место, если x равно нулю, а y равно нулю. [...]

который, насколько я могу судить, означает, что это поведение неуказанное поведение Отключение части бит 7.12.1 Обработка условий ошибки говорит:

[...] ошибка домена возникает, если входной аргумент находится вне домена поверх который определен математической функцией. [...] При ошибке домена функция возвращает значение, определенное реализацией; если целочисленное выражение math_errhandling и MATH_ERRNO отличное от нуля, целочисленное выражение errno приобретает значение EDOM; [...]

Таким образом, если бы была ошибка домена, это было бы определением, определяемым реализацией, но в обеих последних версиях gcc и clang значение errno равно 0, поэтому это не ошибка домена для тех составители.

Обновить Javascript

Для Javascript Спецификация языка ECMAScript® в разделе 15.8 Математический объект в 15.8.2.13 pow (x, y) говорит среди других условий, что:

Если y равно +0, результат равен 1, даже если x является NaN.

Ответ 2

В JavaScript Math.pow определяется следующим образом:

  • Если y является NaN, результатом является NaN.
  • Если y равно +0, результат равен 1, даже если x является NaN.
  • Если y равно -0, результат равен 1, даже если x является NaN.
  • Если x является NaN и y отличен от нуля, результатом является NaN.
  • Если abs (x) > 1 и y равно + ∞, результат равен + ∞.
  • Если abs (x) > 1 и y равно -∞, результат равен +0.
  • Если abs (x) == 1 и y равно + ∞, результат равен NaN.
  • Если abs (x) == 1 и y равно -∞, результат равен NaN.
  • Если abs (x) < 1 и y равно + ∞, результат равен +0.
  • Если abs (x) < 1 и y равно -∞, результат равен + ∞.
  • Если x равно + ∞ и y > 0, результат равен + ∞.
  • Если x равно + ∞ и y < 0, результат равен +0.
  • Если x - -∞ и y > 0, а y - нечетное целое число, результат равен -∞.
  • Если x - -∞ и y > 0, а y не является нечетным целым числом, то результат равен + ∞.
  • Если x - -∞ и y < 0, а y - нечетное целое число, результат равен -0.
  • Если x is -∞ и y < 0 и y не является нечетным целым числом, результат равен +0.
  • Если x равно +0 и y > 0, результат равен +0.
  • Если x равно +0 и y < 0, результат равен + ∞.
  • Если x равно -0 и y > 0, а y - нечетное целое число, результат равен -0.
  • Если x равно -0 и y > 0, а y не является нечетным целым числом, результат равен +0.
  • Если x равно -0 и y < 0, а y - нечетное целое число, результат равен -∞.
  • Если x равно -0 и y < 0, а y не является нечетным целым числом, то результат равен + ∞.
  • Если x < 0 и x конечны и y конечен, а y не является целым числом, то результатом является NaN.

акцент мой

как правило, родные функции для любого языка должны работать, как описано в спецификации языка. Иногда это включает явно "поведение undefined", где оно должно быть реализовано разработчиком, чтобы определить, каким должен быть результат, однако это не относится к поведению undefined.

Ответ 3

Просто условно определить его как 1, 0 или оставить его undefined. Определение pow(0,0) широко распространено из-за следующего определения:

mathematical power definition


Документация ECMA- Script гласит следующее о pow(x,y):

  • Если y равно +0, результат равен 1, даже если x является NaN.
  • Если y равно -0, результат равен 1, даже если x является NaN.

[http://www.ecma-international.org/ecma-262/5.1/#sec-15.8.2.13]

Ответ 4

Согласно Википедии:

В большинстве настроек, не связанных с непрерывностью в экспоненте, интерпретация 0 0 как 1 упрощает формулы и устраняет необходимость в особых случаях в теоремах.

Существует несколько возможных способов лечения 0**0 с плюсами и минусами каждого (см. Wikipedia для расширенного обсуждения).

Стандарт с плавающей запятой IEEE 754-2008 рекомендует три различные функции:

  • pow рассматривает 0**0 как 1. Это самая старая версия. Если мощность является точным целым, результат будет таким же, как и для pown, иначе результат будет таким же, как и для powr (за исключением некоторых исключительных случаев).
  • pown обрабатывает 0 ** 0 как 1. Мощность должна быть точным целым числом. Значение определено для отрицательных оснований; например, pown(−3,5) составляет −243.
  • powr обрабатывает 0 ** 0 как NaN (Not-a-Number - undefined). Значение также NaN для таких случаев, как powr(−3,2), где база меньше нуля. Значение определяется значением exp (power '× log (base)).

Ответ 5

Дональд Кнут

отчасти решила эту дискуссию в 1992 году со следующим:

enter image description here

И еще более подробно описал в своей статье Две заметки о нотации.

В принципе, хотя мы не имеем 1 как предел f(x)/g(x) для всех не всех функций f(x) и g(x), он все же делает комбинаторику намного проще определять 0^0=1, а затем просто делать специальные случаи в тех немногих местах, где вам нужно рассмотреть такие функции, как 0^x, которые в любом случае являются странными. Ведь x^0 появляется намного чаще.

Некоторые из лучших обсуждений, которые я знаю об этой теме (кроме бумаги Кнута):

Ответ 6

Если вы хотите узнать, какое значение вы должны дать f(a), когда f не может быть непосредственно вычислимым в a, вы вычисляете предел f, когда x стремится к a.

В случае x^y обычные пределы стремятся к 1, когда x и y стремятся к 0, и особенно x^x стремится к 1, когда x стремится к 0.

См. http://www.math.hmc.edu/funfacts/ffiles/10005.3-5.shtml

Ответ 7

Определение языка C говорит (7.12.7.4/2):

Ошибка домена может возникнуть, если x равно нулю, а y равно нулю.

В нем также говорится (7.12.1/2):

При ошибке домена функция возвращает значение, определенное реализацией; если целочисленное выражение math_errhandling и MATH_ERRNO отличное от нуля, целочисленное выражение errno приобретает значение EDOM; если целочисленное выражение math_errhandling и MATH_ERREXCEPT отличное от нуля, возникает недопустимое исключение с плавающей запятой.

По умолчанию значение math_errhandling равно MATH_ERRNO, поэтому проверьте errno на значение EDOM.

Ответ 8

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

Экспоненциация на самом деле не соответствует этим другим математическим обозначениям, поэтому определение, которое мы все изучаем, оставляет место для путаницы. Немного другой способ приближения к нему - сказать, что a ^ b (или exp (a, b), если хотите) возвращает значение мультипликативно эквивалентное для умножения некоторой другой вещи через a, повторяется b раз.

Когда мы умножаем 5 на 4, 2 раза, получаем 80. Мы умножили 5 на 16. Итак, 4 ^ 2 = 16.

Когда вы умножаете 14 на 0, 0 раз, мы остаемся с 14. Мы умножили его 1. Следовательно, 0 ^ 0 = 1.

Эта линия мышления может также помочь прояснить отрицательные и дробные показатели. 4 ^ (- 2) является шестнадцатым, потому что "отрицательное умножение" является делением - мы делим на четыре раза.

a ^ (1/2) является корнем (a), потому что умножение чего-либо на корень a составляет половину мультипликативной работы, умножая ее на себя - вам придется сделать это дважды умножить что-то на 4 = 4 ^ 1 = (4 ^ (1/2)) ^ 2

Ответ 9

Чтобы это понять, вам нужно решить исчисление:

введите описание изображения здесь

Развернув x^x вокруг нуля с помощью серии Тейлора, получим:

введите описание изображения здесь

Итак, чтобы понять, что происходит с пределом, когда x обращается в нуль, нам нужно выяснить, что происходит со вторым членом x log(x), поскольку другие члены пропорциональны x log(x), поднятым до некоторой степени.

Нам нужно использовать преобразование:

введите описание изображения здесь

Теперь после этого преобразования мы можем использовать правило L'Hôpital, в котором говорится, что:

введите описание изображения здесь

Итак, дифференцируем это преобразование:

введите описание изображения здесь

Итак, мы вычислили, что термин log(x)*x приближается к 0, когда x приближается к 0. Легко видеть, что другие последовательные члены также приближаются к нулю и даже быстрее второго члена.

Итак, в точке x=0 серия становится 1 + 0 + 0 + 0 + ... и, следовательно, равна 1.