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

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

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

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

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

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

ЗАЧЕМ?

Я знаю это:

>Math.pow(0.001, 0.001)
0.9931160484209338

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

9 ответов

Решение

В C++ Результатом 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 приближается а.

Обновление C++

Как правильно указал Лимес, я изначально ссылался на ссылку для сложной версии pow, в то время как для некомплексной версии утверждается, что это ошибка домена, черновой стандарт C++ возвращается к черновому стандарту C, а также к C99 и C11 в разделе. 7.12.7.4 Пункт2 функций 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.

В 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 равен −∞ и 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.

акцент мой

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

Это просто соглашение, чтобы определить его как 1, 0 или оставить это undefined, Определение POW (0,0 широко распространен из-за следующего определения:

математическое определение силы


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

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

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

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

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

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

Стандарт 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)).

Дональд Кнут

В 1992 году эта дискуссия была решена следующим образом:

И еще больше углубился в детали в своей статье " Две заметки о записи".

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

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

Когда вы хотите знать, какую ценность вы должны дать 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

Определение языка 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,

Я хотел бы не согласиться с утверждением некоторых предыдущих ответов о том, что это вопрос соглашения или удобства (охватывающий некоторые особые случаи для различных теорем и т. Д.), Что 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) - 16-е, потому что "отрицательное умножение" - это деление - мы делим на четыре дважды.

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

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

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

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

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

Теперь после этой трансформации мы можем использовать правило Л'Опитала, которое гласит:

Таким образом, дифференцируя это преобразование, мы получаем:

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

Итак, в момент x=0сериал становится 1 + 0 + 0 + 0 + ... и, таким образом, равен 1.

Другие вопросы по тегам