88

我们都知道 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.

4

9 回答 9

79

在 C++中 pow(0, 0)的结果基本上是实现定义的行为,因为在数学上我们有一个矛盾的情况,N^0应该总是10^N应该总是0for N > 0,所以你也不应该对结果有数学期望。这篇Wolfram Alpha论坛帖子介绍了更多细节。

尽管pow(0,0)结果 in1对于许多应用程序很有用,因为国际标准的基本原理 - 编程语言 - C在涵盖IEC 60559 浮点算术支持的部分中声明:

通常,C99 避免使用数值有用的 NaN 结果。[...] pow(∞,0) 和 pow(0,0) 的结果都是 1,因为有些应用程序可以利用这个定义。例如,如果 x(p) 和 y(p) 是在 p = a 处变为零的任何解析函数,则等于 exp(y*log(x)) 的 pow(x,y) 在 p 接近时接近 1一个。

更新 C++

正如 leemes 正确指出的那样,我最初链接到复杂版本pow的参考,而非复杂版本声称这是域错误C++ 标准草案回退到C 标准草案以及C99C11部分中7.12.7.4 的 pow 函数2说(强调我的):

[...]如果 x 为零且 y 为零,则可能发生域错误。[...]

据我所知,这意味着这种行为是未指定的行为回退一点7.12.1 错误条件的处理说:

[...]如果输入参数在定义数学函数的域之外,则会发生域错误。[...]在域错误时,函数返回实现定义的值;如果整数表达式 math_errhandling & MATH_ERRNO 非零,则整数表达式 errno 获取值 EDOM;[...]

因此,如果存在域错误,那么这将是实现定义的行为,但在最新版本gcc和isclang的值中,对于那些编译器来说,这不是域错误。errno0

更新 Javascript

对于Javascript ,在pow (x, y)的数学对象部分中的ECMAScript® 语言规范说明了以下条件:15.8 15.8.2.13

如果 y 为 +0,则结果为 1,即使 x 为 NaN。

于 2013-11-13T14:14:33.487 回答
35

在 JavaScriptMath.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。

强调我的

作为一般规则,任何语言的本机函数都应该按照语言规范中的描述工作。有时这包括明确的“未定义行为”,由实施者决定结果应该是什么,但这不是未定义行为的情况。

于 2013-11-13T14:16:05.797 回答
16

1将其定义为0或保留它只是惯例undefined。由于以下定义,该定义战俘(0,0)被广泛传播:

数学幂定义


ECMA-Script 文档对以下内容进行了说明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 ]

于 2013-11-13T14:29:13.560 回答
14

根据维基百科:

在大多数不涉及指数连续性的设置中,将 0 0解释为 1 可以简化公式并消除定理中对特殊情况的需要。

有几种可能的方法来处理0**0每种方法的优缺点(有关详细讨论,请参见Wikipedia)。

IEEE 754-2008浮点标准推荐了三种不同的函数:

  • pow视为. 0**0_ 1这是最早定义的版本。如果幂是精确整数,则结果与 for 相同pown,否则结果与 forpowr相同(某些例外情况除外)。
  • pown将 0**0 视为 1。幂必须是精确整数。该值是为负数定义的;例如,pown(−3,5)−243
  • powr将 0**0 视为 NaN(非数字 - 未定义)。powr(−3,2)对于基数小于零的情况,该值也是 NaN 。该值由 exp(power'×log(base)) 定义。
于 2013-11-13T14:30:49.943 回答
7

唐纳德·克努特

在 1992 年以下列方式解决了这场辩论:

在此处输入图像描述

并在他的论文中对符号的两个注释进行了更详细的介绍。

基本上,虽然我们没有将 1 作为f(x)/g(x)并非所有函数f(x)和的限制g(x),但它仍然使组合数学的定义变得如此简单0^0=1,然后只需在需要考虑函数的少数地方进行特殊情况,0^x例如反正很奇怪。毕竟x^0出现的频率更高。

我所知道的关于这个主题的一些最好的讨论(除了 Knuth 论文)是:

于 2013-12-04T13:03:12.007 回答
5

C 语言定义说 (7.12.7.4/2):

如果 x 为零且 y 为零,则可能发生域错误。

它还说(7.12.1/2):

在域错误时,该函数返回一个实现定义的值;如果整数表达式 math_errhandling & MATH_ERRNO 非零,则整数表达式 errno 获取值 EDOM;如果整数表达式 math_errhandling & MATH_ERREXCEPT 不为零,则引发“无效”浮点异常。

默认情况下, 的值为math_errhandlingMATH_ERRNO因此请检查errno该值EDOM

于 2013-11-13T14:26:28.847 回答
5

当您想知道f(a)f不能直接计算时应该赋予什么值时a,您可以计算f何时x趋于的极限a

在这种情况下x^y,通常的限制倾向于1何时xy倾向于0,尤其是x^x倾向于1何时x倾向于0

http://www.math.hmc.edu/funfacts/files/10005.3-5.shtml

于 2013-11-13T14:17:45.990 回答
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 位,因为“负乘法”是除法——我们除以四两次。

a^(1/2) 是 root(a),因为将某物乘以 a 的根是乘以 a 本身的乘法工作的一半——你必须做两次才能将某物乘以 4 = 4^1 = (4^(1/2))^2

于 2013-12-06T18:31:12.700 回答
0

要理解这一点,您需要解决微积分:

在此处输入图像描述

x^x使用泰勒级数在零附近展开,我们得到:

在此处输入图像描述

因此,要了解 limitx变为零时发生了什么,我们需要找出 second term 发生了什么x log(x),因为其他项与x log(x)提高到某个幂成正比。

我们需要使用转换:

在此处输入图像描述

现在经过这个转换,我们可以使用L'Hôpital 规则,它指出:

在此处输入图像描述

所以区分我们得到的转换:

在此处输入图像描述

所以我们计算出log(x)*x当 x 接近 0 时,项接近 0。很容易看出,其他连续项也接近 0,甚至比第二项更快。

所以在 点x=0,系列变为1 + 0 + 0 + 0 + ...并因此等于 1。

于 2015-11-03T16:26:32.250 回答