2013-11-13 1 views
80

Мы все знаем, что 0 неопределен.Почему Math.pow (0, 0) === 1?

Но, 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.

+3

@zzzzBov: Под стандартной четкости, "а б = ехр (Ь п (а))", это не определено. Попытка определить его как «предел x-> 0 f (x) g (x)« где «f» и «g» оба имеют пределы нуля, дает неопределенное значение, поскольку оно зависит от вашего выбора функций , (Извинения за искаженные обозначения, я не могу понять, как получить надписи в комментариях). –

+0

@MikeSeymour, да, я знаю, что 0⁰ (использование символов Unicode) не определено, учитывая это определение, однако, если вы читаете мой комментарий, вы должны заметить, что цитата ссылается на «мир математики», а не на любое «стандартное определение», , Это различие, что я изначально ссылался, и вопрос был обновлен, чтобы исправить этот нюанс. – zzzzBov

+2

@AJMansfield Um ... a^0 = 1 для ненулевого a. – Beska

ответ

77

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

Хотя с pow(0,0) результатом в 1 полезно для многих приложений как Rationale for International Standard—Programming Languages—C состояний в секции покрытие МЭК 60559 арифметики с плавающей точкой поддержки:

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

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

Как leemes правильно указал, что я изначально связан с ссылкой на версию мощн в комплекс в то время как версия non-complex утверждает, что это ошибка домен по draft C++ standard падает обратно до draft C standard и оба C99 и C11 в разделе 7.12.7.4Функции POW пункт говорит (курсив мой ).

[...] Ошибка домена может произойти если х равен нулю, а у равен нулю [...]

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

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

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

Обновление Javascript

Для JavascriptECMAScript® Language Specification в разделе 15.8Математика Объект под 15.8.2.13мощн (х, у) говорит среди других условий, которые:

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

+1

@leemes Я считаю, что страница неверна, стандарт не говорит о том, что NaN должен быть возвращен. Возвращаемое значение определяется реализацией. cplusplus.com, который, как вы утверждаете, не является надежным источником, на самом деле более точен. – interjay

+0

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

+0

@leemes сообщество C++ на SO [определенно сильно не нравится в cplusplus.com] (http://meta.stackexchange.com/questions/194788/links-being-changed-to-cppreference-com) –

34

In JavaScript Math.pow is defined as follows:

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

курсив мой

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

+0

Приложение F в стандартах C99 и C11 содержит эту же спецификацию.Предполагается, что реализация должна определить '__STDC_IEC_559__', чтобы сообщить, что она соответствует этой спецификации. Приложение F описывает арифметику с плавающей точкой IEC 60559. Я считаю, что спецификация С разрешена частично соответствовать Приложению F (например, pow (0, 0) == 1), а не определять '__STDC_IEC_559__'. –

+0

@HowardHinnant hmmm, кажется, что в случае [gcc] (https://groups.google.com/forum/#!topic/gnu.gcc.help/P4vx6fnqDGg) и [clang] (https: // исходная программа .org/bugzilla/show_bug.cgi? id = 6981) эта часть информации может быть не совсем полезной, что обескураживает. –

+6

Я не знаю, что этот ответ помогает. Конечно, функция должна выполняться так, как она определена в спецификации. Но тогда вопрос просто становится «Почему он был определен таким образом в спецификации?» – Beska

5

Если вы хотите знать, какое значение вы должны дать 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

5

говорит: C (7.12.7.4/2):

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

Он также говорит (7.12.1/2):

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

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

+1

Whoups! Это действительно интересно! Я скомпилировал свой файл cpp с помощью 'g ++ (Ubuntu/Linaro 4.8.1-10ubuntu8) 4.8.' –

16

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

mathematical power definition


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

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

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

+3

math.stackexchange имеет много хороших обсуждений и объяснений для определения 0^0 = 1: http://math.stackexchange.com/questions/11150/zero-to-the-zero-power-is-00-1 – PLL

14

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

В большинстве установок, не связанных с обрывами в показателе, интерпретируя 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 (не-номер - неопределенный). Значение также NaN для таких случаев, как powr(−3,2), где основание меньше нуля. Значение определяется значением exp (power '× log (base)).
6

Дональд Кнут

рода решен этот спор в 1992 году следующее:

enter image description here

И пошел еще в подробности в своей статье Two Notes on Notation.

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

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

+0

Интересная информация! –

+0

Если вы еще не прочитали, прочитайте ответы в [Нуль до нулевой мощности ...?] (Http://math.stackexchange.com/questions/11150/zero-to-the-zero-power-is-00 -1), который был связан с вопросом о том, что некоторые из ответов также касаются этого подхода. –

0

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

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

0

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

enter image description here

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

enter image description here

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

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

enter image description here

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

enter image description here

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

enter image description here

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

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

+0

Хотя этот ответ впечатляет, стоит отметить, что в математике предел при х -> а функции f (x) не обязательно равен f (a), если только функция не непрерывна в точке x. – jasonszhao