为什么Math.pow(0,0)=== 1?
我们都知道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
。
在C ++ 中pow(0,0)的结果基本上是实现定义的行为,因为在math上我们有一个矛盾的情况,其中N^0
应该总是1
但是对于N > 0
0^N
应该总是N > 0
,所以你应该有math上也没有任何期望的结果。 这个Wolfram Alpha论坛post进入了更多的细节。
尽pipe在IEC 60559浮点算术支持的章节中将pow(0,0)
为1
对于许多应用程序是有用的,如国际标准编程语言-C语言的原理 :
通常,C99在数值有用时避开NaN结果。 pow(∞,0)和pow(0,0)的结果都是1,因为有些应用可以利用这个定义。 例如,如果x(p)和y(p)是在p = a时变为零的任何parsing函数,那么等于exp(y * log(x))的pow(x,y)随着p逼近而接近1一个。
更新C ++
正如leemes正确指出的那样,我原来是和pow的复杂版本的引用关联的, 而非复杂的版本声称是域错误,所以C ++标准草案会回落到草案C标准中 ,并且在7.12.7.4
节中都是C99和C11 pow函数第2段说( 强调我的 ):
[…]如果x为零且y为零,则可能会出现域错误。
据我所知这意味着这种行为是未指定的行为回绕一点7.12.1
错误条件的处理说:
[…]如果input参数超出定义math函数的域,就会出现域错误[…]在域错误上,函数返回实现定义的值; 如果整数expression式math_errhandling&MATH_ERRNO不为零,则整型expression式errno获取EDOM值; […]
所以如果有一个域错误,那么这将是实现定义的行为,但在最新版本的gcc
和clang
中, errno
的值是0
所以这不是这些编译器的域错误 。
更新Javascript
对于Javascript , ECMAScript®语言规范第15.8
节中的 15.8.2.13
pow(x,y)下的Math对象说除其他条件:
如果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。
强调我的
作为一般规则,任何语言的原生函数都应该按照语言规范中的描述进行工作。 有时候,这包括明确的“未定义的行为”,由实施者决定结果应该是什么,然而这不是未定义的行为。
将它定义为0
或者将其undefined
只是约定。 定义 由于以下定义而广泛传播:
ECMA脚本文档说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 ]
根据维基百科:
在大多数不涉及指数连续性的情况下,将0 0解释为1可以简化公式,并且不需要定理中的特殊情况。
有几种可能的方法来处理0**0
的优点和缺点(见维基百科进行扩展讨论)。
IEEE 754-2008浮点标准推荐三种不同的function:
-
pow
把0**0
当作1
。 这是最早定义的版本。 如果权力是一个精确的整数,结果与pown
相同,否则结果是pown
(除了一些例外情况)。 -
pown
将0 ** 0视为1.权力必须是一个确切的整数。 该值定义为负数基数; 例如,pown(−3,5)
是−243
。 -
powr
将0 ** 0视为NaN(Not-a-Number – 未定义)。 对于类似powr(−3,2)
情况,这个值也是NaN,其中基数小于零。 该值由exp(power'×log(base))定义。
唐纳德Knuth
这种争论在1992年得到了解决,具体如下:
在他的论文“ Two Notation on Notation”中进一步讨论了细节。
基本上,尽pipe对于所有函数f(x)
和g(x)
,我们没有1作为f(x)/g(x)
的极限,但它仍然使得组合方法更容易定义0^0=1
,然后在less数需要考虑0^x
函数的地方做一些特殊情况,这些都是奇怪的。 毕竟x^0
经常出现。
我所知道的关于这个主题的一些最好的讨论(Knuth论文除外)是:
当你想知道你应该给f(a)
什么值,当f
不能直接在a
计算时,你计算f
的极限,当x
倾向于a
。
在x^y
情况下,当x
和y
倾向于0
时,通常的限制倾向于1
,并且特别是当x
倾向于0
时x
x^x
倾向于1
。
C语言定义说(7.12.7.4/2):
如果x为零且y为零,则可能会出现域错误。
它也说(7.12.1 / 2):
在域错误上,该函数返回一个实现定义的值; 如果整数expression式math_errhandling&MATH_ERRNO不为零,则整型expression式errno获取EDOM值; 如果整数expression式math_errhandling&MATH_ERREXCEPT为非零,则会引发“无效的”浮点exception。
默认情况下, math_errhandling
的值是MATH_ERRNO
,因此请检查errno
的值EDOM
。
我不同意以前的一些答案,认为这是一个约定或方便的问题(包括各种定理的一些特殊情况等),0 ^ 0定义为1而不是0。
幂乘实际上并不符合我们的其他math符号,所以我们都学习的定义留下了混淆的余地。 接近它的一个稍微不同的方法是说a ^ b(或者exp(a,b),如果你喜欢的话)返回等于乘以某个其他东西的值,重复b次。
当我们乘以5乘以4,乘以2,得到80,乘以5乘以16,所以4 ^ 2 = 16。
当你乘以14,乘以0,乘以14,我们乘以1.因此,0 ^ 0 = 1。
这一思路也可能有助于澄清负数和小数指数。 4 ^( – 2)是16号,因为“负乘法”是除法 – 我们除以4。
a ^(1/2)是根(a),因为用a的根乘以一半的乘法工作就是把它乘以一个自身 – 你必须做两次乘以4 = 4 ^ 1 = (4 ^(1/2))^ 2
为了了解你需要解决微积分:
使用泰勒级数展开零点附近的x^x
,我们得到:
因此,要知道当x
变为零时有什么限制,我们需要找出第二项x log(x)
发生了什么,因为其他项与x log(x)
成比例地boost到某个能力。
我们需要使用转换:
现在经过这个转变,我们可以使用L'Hôpital的规定 ,规定:
所以区分我们得到的转变:
所以我们计算了当log(x)*x
接近0时, log(x)*x
接近于零。很容易看出其他连续项也接近于零,甚至比第二项更快。
所以在x=0
点,系列变成1 + 0 + 0 + 0 + ...
因此等于1。