Все мы знаем, что 0 0 неопределенно.
Но , 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
.
javascript
c++
language-agnostic
pow
Ионика Бизэу
источник
источник
Ответы:
В C ++ в
результате мощно (0, 0)результат в основном определяется реализация поведения , поскольку математически мы имеем противоречивую ситуацию , в которойN^0
всегда должно быть ,1
но0^N
всегда должно быть0
наN > 0
, так что вы не должны иметь никаких ожиданий математически в результате этого либо. Эти сообщения на форуме Wolfram Alpha содержат более подробную информацию.Хотя
pow(0,0)
результат1
полезен для многих приложений, так как в Обосновании международного стандарта - Языки программирования - C говорится в разделе, посвященном поддержке арифметики с плавающей запятой МЭК 60559 :Обновить C ++
Как leemes правильно указал , что я изначально связанно с ссылкой на комплексную версию мощна в то время как несложная версию утверждает , что это ошибка домена проекта стандарта C ++ возвращается к проекту стандарта C и как С99 и С11 в разделе
7.12.7.4
военнопленной функции пункт 2 говорит ( выделено мной ):что, насколько я могу судить, означает, что это поведение является неопределенным. Перемотка назад битового раздела
7.12.1
Обработка условий ошибки говорит:Так что если была ошибка домена , то это будет реализация определяется поведение , но в обоих последних версиях
gcc
иclang
стоимостиerrno
является0
так это не ошибка домена для этих компиляторов.Обновить Javascript
Для Javascript в спецификации языка ECMAScript® в разделе
15.8
«Математический объект» под15.8.2.13
pow (x, y) среди других условий говорится, что:источник
В JavaScript
Math.pow
определяется следующим образом :акцент мой
Как правило, собственные функции для любого языка должны работать, как описано в спецификации языка. Иногда это включает явно «неопределенное поведение», когда разработчик должен определить, каким должен быть результат, однако это не случай неопределенного поведения.
источник
__STDC_IEC_559__
объявляет, что она соответствует этой спецификации. Приложение F описывает арифметические операции с плавающей запятой МЭК 60559. Я считаю, что спецификации C разрешено частично соответствовать Приложению F (например, pow (0, 0) == 1), а не определять__STDC_IEC_559__
.Это просто условность определить его как
1
,0
или оставить егоundefined
. Определение широко распространено из-за следующего определения:В документации ECMA-Script говорится следующее
pow(x,y)
:[ http://www.ecma-international.org/ecma-262/5.1/#sec-15.8.2.13 ]
источник
Согласно Википедии:
Есть несколько возможных способов лечения,
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):
В нем также говорится (7.12.1 / 2):
По умолчанию значение
math_errhandling
равноMATH_ERRNO
, поэтому проверьтеerrno
значениеEDOM
.источник
g++ (Ubuntu/Linaro 4.8.1-10ubuntu8) 4.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) - 16-е, потому что «отрицательное умножение» - это деление - мы делим на четыре дважды.
a ^ (1/2) - это корень (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.источник