Todos sabemos que 0 0 es indeterminado.
Pero , javascript dice que:
Math.pow(0, 0) === 1 // true
y C ++ dice lo mismo:
pow(0, 0) == 1 // true
¿POR QUÉ?
Yo sé eso:
>Math.pow(0.001, 0.001)
0.9931160484209338
Pero, ¿por qué no Math.pow(0, 0)
arroja errores? O tal vez NaN
sería mejor que 1
.
javascript
c++
language-agnostic
pow
Ionică Bizău
fuente
fuente
Respuestas:
En C ++
El resultado de pow (0, 0)el resultado es básicamente un comportamiento definido por la implementación ya que matemáticamente tenemos una situación contradictoria dondeN^0
siempre debería estar1
pero0^N
siempre debería ser0
paraN > 0
, por lo que tampoco debería tener expectativas matemáticas en cuanto al resultado de esto. Este Wolfram Alpha mensajes en el foro entra en un poco más de detalles.Aunque tener un
pow(0,0)
resultado en1
es útil para muchas aplicaciones, ya que la Justificación de la Norma Internacional — Lenguajes de programación — C establece en la sección que cubre el soporte aritmético de coma flotante IEC 60559 :Actualizar C ++
Como leemes señaló correctamente, originalmente me vinculé a la referencia para la versión compleja de pow mientras que la versión no compleja afirma que es un error de dominio, el borrador del estándar C ++ recurre al borrador del estándar C y tanto C99 como C11 en la sección
7.12.7.4
El párrafo de funciones de pow 2 dice ( énfasis mío ):lo que, por lo que puedo decir, significa que este comportamiento es un comportamiento no especificado Rebobinando una sección de bits El
7.12.1
tratamiento de las condiciones de error dice:Entonces, si hubiera un error de dominio , este sería un comportamiento definido por la implementación, pero tanto en las últimas versiones de
gcc
como enclang
el valor deerrno
es,0
por lo que no es un error de dominio para esos compiladores.Actualizar Javascript
Para Javascript, la Especificación del lenguaje ECMAScript® en la sección
15.8
El objeto matemático bajo15.8.2.13
pow (x, y) dice, entre otras condiciones, que:fuente
En JavaScript
Math.pow
se define de la siguiente manera :énfasis mío
como regla general, las funciones nativas de cualquier idioma deberían funcionar como se describe en la especificación del idioma. A veces esto incluye explícitamente "comportamiento indefinido" en el que depende del implementador determinar cuál debería ser el resultado, sin embargo, este no es un caso de comportamiento indefinido.
fuente
__STDC_IEC_559__
para anunciar que se ajusta a esta especificación. El anexo F describe la aritmética de coma flotante IEC 60559. Creo que una especificación C puede cumplir parcialmente con el Anexo F (por ejemplo, pow (0, 0) == 1) y no definir__STDC_IEC_559__
.Es una convención definirlo como
1
,0
o dejarloundefined
. La definición está muy extendida debido a la siguiente definición:La documentación de ECMA-Script dice lo siguiente sobre
pow(x,y)
:[ http://www.ecma-international.org/ecma-262/5.1/#sec-15.8.2.13 ]
fuente
Según Wikipedia:
Hay varias formas posibles de tratar
0**0
con los pros y los contras de cada uno (consulte Wikipedia para una discusión más extensa).El estándar de punto flotante IEEE 754-2008 recomienda tres funciones diferentes:
pow
trata0**0
como1
. Ésta es la versión definida más antigua. Si la potencia es un entero exacto, el resultado es el mismo que parapown
, de lo contrario, el resultado es como parapowr
(salvo algunos casos excepcionales).pown
trata 0 ** 0 como 1. La potencia debe ser un número entero exacto. El valor se define para bases negativas; por ejemplo,pown(−3,5)
es−243
.powr
trata 0 ** 0 como NaN (Not-a-Number - undefined). El valor también es NaN para casos comopowr(−3,2)
donde la base es menor que cero. El valor está definido por exp (potencia '× log (base)).fuente
Donald Knuth
de alguna manera resolvió este debate en 1992 con lo siguiente:
Y entró aún más en detalles en su artículo Two Notes on Notation .
Básicamente, mientras que no tenemos 1 como el límite de
f(x)/g(x)
para todos no todas las funcionesf(x)
yg(x)
, todavía tiene la combinatoria de manera mucho más simple de definir0^0=1
, y luego simplemente hacemos casos especiales en los pocos lugares donde se necesita tener en cuenta las funciones, tales como0^x
, la cual son raros de todos modos. Después de todo,x^0
surge mucho más a menudo.Algunas de las mejores discusiones que conozco sobre este tema (además del artículo de Knuth) son:
fuente
Cuando desee saber a qué valor debe dar
f(a)
cuandof
no es directamente computablea
, calcula el límite def
cuandox
tiende haciaa
.En el caso de
x^y
, los límites habituales tienden hacia1
cuándox
yy
tienden0
, y sobre todox^x
tiende hacia1
cuándox
tiende0
.Ver http://www.math.hmc.edu/funfacts/ffiles/10005.3-5.shtml
fuente
La definición del lenguaje C dice (7.12.7.4/2):
También dice (7.12.1 / 2):
De forma predeterminada, el valor de
math_errhandling
esMATH_ERRNO
, así que verifiqueerrno
el valorEDOM
.fuente
g++ (Ubuntu/Linaro 4.8.1-10ubuntu8) 4.8.
Me gustaría no estar de acuerdo con la afirmación de algunas de las respuestas anteriores de que es una cuestión de convención o conveniencia (que cubre algunos casos especiales para varios teoremas, etc.) que 0 ^ 0 se defina como 1 en lugar de 0.
La exponenciación en realidad no encaja tan bien con nuestras otras notaciones matemáticas, por lo que la definición que todos aprendemos deja lugar a la confusión. Una forma ligeramente diferente de abordarlo es decir que a ^ b (o exp (a, b), si lo desea) devuelve el valor multiplicativamente equivalente a multiplicar alguna otra cosa por a, repetido b veces.
Cuando multiplicamos 5 por 4, 2 veces, obtenemos 80. Hemos multiplicado 5 por 16. Entonces 4 ^ 2 = 16.
Cuando multiplica 14 por 0, 0 veces, nos queda 14. Lo hemos multiplicado 1. Por lo tanto, 0 ^ 0 = 1.
Esta línea de pensamiento también podría ayudar a aclarar exponentes negativos y fraccionarios. 4 ^ (- 2) es un dieciseisavo, porque la 'multiplicación negativa' es una división; dividimos por cuatro dos veces.
a ^ (1/2) es raíz (a), porque multiplicar algo por la raíz de a es la mitad del trabajo multiplicativo que multiplicarlo por a sí mismo; tendrías que hacerlo dos veces para multiplicar algo por 4 = 4 ^ 1 = (4 ^ (1/2)) ^ 2
fuente
Para que esto se entienda, necesitas resolver cálculo:
Al expandir
x^x
alrededor de cero usando la serie de Taylor, obtenemos:Entonces, para entender qué está sucediendo con el límite cuando
x
llega a cero, necesitamos averiguar qué está sucediendo con el segundo términox log(x)
, porque otros términos son proporcionales ax log(x)
elevar a alguna potencia.Necesitamos usar la transformación:
Ahora, después de esta transformación, podemos usar la regla de L'Hôpital , que establece que:
Así que diferenciando esa transformación obtenemos:
Así que hemos calculado que el término se
log(x)*x
acerca a 0 cuando x se acerca a 0. Es fácil ver que otros términos consecutivos también se acercan a cero e incluso más rápido que el segundo término.Entonces, en el punto
x=0
, la serie se vuelve1 + 0 + 0 + 0 + ...
y, por lo tanto, es igual a 1.fuente