我们都知道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)
抛出错误呢?也许aNaN
会比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)
抛出错误呢?也许aNaN
会比1
。
Answers:
在C ++中,pow(0,0)的结果基本上是实现定义的行为,因为在数学上我们有一个矛盾的情况,N^0
应该始终1
但0^N
应该始终是0
for N > 0
,因此您在数学上也不应该对此期望任何结果。这Wolfram Alpha的论坛帖子进入多一点细节。
尽管pow(0,0)
产生结果1
对于许多应用程序都是有用的,因为涵盖IEC 60559浮点算术支持的部分中指出了国际标准(编程语言)C的状态:
通常,C99避开NaN结果,而数值是有用的。[...] pow(∞,0)和pow(0,0)的结果均为1,因为有些应用程序可以利用此定义。例如,如果x(p)和y(p)是在p = a处变为零的任何解析函数,则pow(x,y)等于exp(y * log(x)),随着p接近,其逼近1一种。
更新C ++
正如leemes正确地指出我最初链接为基准复杂的版本POW而不复杂的版本权利要求它是域误差的草案C ++标准回落到草案C标准和两个C99和C11中部分7.12.7.4
的POW功能段2说(强调我的):
[...]如果x为零且y为零,则可能会发生域错误。[...]
其中,据我可以告诉手段这种行为是不确定的行为绕组回位段7.12.1
的错误疾病的治疗说:
如果输入参数在定义数学函数的域之外,则会发生域错误。发生域错误时,该函数将返回实现定义的值;否则会出现错误。如果整数表达式math_errhandling&MATH_ERRNO为非零,则整数表达式errno获取值EDOM;[...]
所以,如果有一个域错误那么这将是实现定义的行为,但在双方的最新版本gcc
和clang
价值errno
是0
,所以它不是一个域误差为那些编译器。
更新Javascript
对于Javascript,pow(x,y)下“数学对象”部分中的ECMAScript®语言规范指出:15.8
15.8.2.13
如果y为+0,则即使x为NaN,结果也为1。
- 如果y为NaN,则结果为NaN。
- 如果y为+0,则即使x为NaN,结果也为1。
- 如果y为−0,则即使x为NaN,结果也为1。
- 如果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。
重点矿
作为一般规则,任何语言的本机功能都应按照语言规范中的说明工作。有时,这包括明确的“未定义行为”,由实施者确定结果应该是什么,但是这不是未定义行为的情况。
__STDC_IEC_559__
为宣布它符合此规范。附件F描述了IEC 60559浮点算法。我认为C规范可以部分符合附件F(例如pow(0,0)== 1),而不是define __STDC_IEC_559__
。
它是将其定义为只是约定1
,0
或者离开它undefined
。该定义由于以下定义而广为流传:
ECMA-Script文档对以下内容进行了说明pow(x,y)
:
- 如果y为+0,则即使x为NaN,结果也为1。
- 如果y为−0,则即使x为NaN,结果也为1。
[ http://www.ecma-international.org/ecma-262/5.1/#sec-15.8.2.13 ]
根据维基百科:
在大多数不涉及指数连续性的设置中,将0 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(非数字-未定义)。对于powr(−3,2)
底数小于零的情况,该值也为NaN 。该值由exp(power'×log(base))定义。通过以下方式解决了这场辩论:
基本上,尽管f(x)/g(x)
并非所有函数f(x)
and都没有1的限制g(x)
,但它仍然使组合函数的定义变得如此简单0^0=1
,然后仅在需要考虑函数的少数地方做特殊情况,例如0^x
,反正很奇怪 毕竟,x^0
出现的频率更高。
我知道的关于该主题的一些最佳讨论(除了Knuth论文)是:
当您想知道应该什么f(a)
时候f
不能直接a
计算的值f
时,您可以计算什么时候x
趋向于极限a
。
在这种情况下x^y
,通常的限制趋于1
何时x
和y
趋于0
,尤其是x^x
趋于1
何时x
趋于0
。
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
。
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的整数,因为“负乘法”是除法运算-我们除以4两次。
a ^(1/2)是root(a),因为将某物乘以a的根是乘以本身乘以一半的乘法工作-您必须做两次以将某物乘以4 = 4 ^ 1 = (4 ^(1/2))^ 2
为了理解这一点,您需要解决微积分:
x^x
使用泰勒级数在零附近展开,我们得到:
因此,要了解x
零时极限发生了什么,我们需要找出第二项发生了什么x log(x)
,因为其他项正比于x log(x)
提高到某种功效。
我们需要使用转换:
现在,在此变换之后,我们可以使用L'Hôpital规则,该规则指出:
因此,使该转换与众不同:
因此,我们已经计算出,log(x)*x
当x接近0时,该项接近0。很容易看到其他连续项也接近零,甚至比第二项还要快。
因此,在点上x=0
,级数变为1 + 0 + 0 + 0 + ...
并因此等于1。