javascript 为什么 Math.pow(0, 0) === 1?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19955968/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why is Math.pow(0, 0) === 1?
提问by Ionic? Biz?u
We all know that 00is indeterminate.
我们都知道 0 0是不确定的。
But, javascriptsays that:
但是,javascript说:
Math.pow(0, 0) === 1 // true
and C++says the same thing:
和C++说同样的话:
pow(0, 0) == 1 // true
WHY?
为什么?
I know that:
我知道:
>Math.pow(0.001, 0.001)
0.9931160484209338
But why does Math.pow(0, 0)
throw no errors? Or maybe a NaN
would be better than 1
.
但是为什么不Math.pow(0, 0)
抛出错误呢?或者也许 aNaN
会比1
.
采纳答案by Shafik Yaghmour
In C++ The result of pow(0, 0)the result is basically implementation defined behavior since mathematically we have a contradictory situation where N^0
should always be 1
but 0^N
should always be 0
for N > 0
, so you should have no expectations mathematically as to the result of this either. This Wolfram Alphaforum posts goes into a bit more details.
在 C++中 pow(0, 0)的结果基本上是实现定义的行为,因为在数学上我们有一个矛盾的情况N^0
应该总是1
但0^N
应该总是0
for N > 0
,所以你也不应该对这个结果有数学上的期望。这个Wolfram Alpha论坛帖子有更多细节。
Although having pow(0,0)
result in 1
is useful for many applications as the Rationale for International Standard—Programming Languages—Cstates in the section covering IEC 60559 floating-point arithmeticsupport:
尽管pow(0,0)
在涵盖IEC 60559 浮点算术支持的部分中,1
作为国际标准的基本原理—编程语言—C状态,结果对于许多应用程序很有用:
Generally, C99 eschews a NaN result where a numerical value is useful. [...] The results of pow(∞,0) and pow(0,0) are both 1, because there are applications that can exploit this definition. For example, if x(p) and y(p) are any analytic functions that become zero at p = a, then pow(x,y), which equals exp(y*log(x)), approaches 1 as p approaches a.
通常,C99 避免使用数值有用的 NaN 结果。[...] pow(∞,0) 和 pow(0,0) 的结果都是 1,因为有些应用程序可以利用这个定义。例如,如果 x(p) 和 y(p) 是任何在 p = a 处变为零的解析函数,那么 pow(x,y),等于 exp(y*log(x)),随着 p 的接近而接近 1一个。
Update C++
更新 C++
As leemes correctly pointed out I originally linked to the reference for the complexversion of powwhile the non-complexversion claims it is domain errorthe draft C++ standardfalls back to the draft C standardand both C99and C11in section 7.12.7.4
The pow functionsparagraph 2says (emphasis mine):
正如leemes正确地指出我最初链接为基准复杂的版本POW而不复杂的版本权利要求它是域误差的草案C ++标准回落到草案C标准和两个C99和C11中部分7.12.7.4
的POW功能段2说(强调我的):
[...]A domain error may occurif x is zero and y is zero.[...]
[...]如果 x 为零且 y 为零,则可能发生域错误。[...]
which as far as I can tell means this behavior is unspecified behaviorWinding back a bit section 7.12.1
Treatment of error conditionssays:
据我所知,这意味着这种行为是未指定的行为,回退一点部分7.12.1
错误条件的处理说:
[...]a domain error occurs if an input argument is outside the domain over which the mathematical function is defined.[...] On a domain error, the function returns an implementation-defined value; if the integer expression math_errhandling & MATH_ERRNO is nonzero, the integer expression errno acquires the value EDOM; [...]
[...]如果输入参数在定义数学函数的域之外,则会发生域错误。[...] 在域错误时,函数返回一个实现定义的值;如果整数表达式 math_errhandling & MATH_ERRNO 非零,则整数表达式 errno 获取值 EDOM;[...]
So if there was a domain errorthen this would be implementation defined behaviorbut in both the latest versions of gcc
and clang
the value of errno
is 0
so it is not a domain errorfor those compilers.
因此,如果存在域错误,那么这将是实现定义的行为,但在最新版本的gcc
和clang
的值中,对于这些编译器errno
来说0
,这不是域错误。
Update Javascript
更新 JavaScript
For Javascriptthe ECMAScript? Language Specificationin section 15.8
The Math Objectunder 15.8.2.13
pow (x, y)says amongst other conditions that:
对于Javascript,ECMAScript?在pow (x, y)下15.8
的数学对象部分中的语言规范说,除其他条件外:15.8.2.13
If y is +0, the result is 1, even if x is NaN.
如果 y 为 +0,则结果为 1,即使 x 为 NaN。
回答by zzzzBov
In JavaScript Math.pow
is defined as follows:
- If y is NaN, the result is NaN.
- If y is +0, the result is 1, even if x is NaN.
- If y is ?0, the result is 1, even if x is NaN.
- If x is NaN and y is nonzero, the result is NaN.
- If abs(x)>1 and y is +∞, the result is +∞.
- If abs(x)>1 and y is ?∞, the result is +0.
- If abs(x)==1 and y is +∞, the result is NaN.
- If abs(x)==1 and y is ?∞, the result is NaN.
- If abs(x)<1 and y is +∞, the result is +0.
- If abs(x)<1 and y is ?∞, the result is +∞.
- If x is +∞ and y>0, the result is +∞.
- If x is +∞ and y<0, the result is +0.
- If x is ?∞ and y>0 and y is an odd integer, the result is ?∞.
- If x is ?∞ and y>0 and y is not an odd integer, the result is +∞.
- If x is ?∞ and y<0 and y is an odd integer, the result is ?0.
- If x is ?∞ and y<0 and y is not an odd integer, the result is +0.
- If x is +0 and y>0, the result is +0.
- If x is +0 and y<0, the result is +∞.
- If x is ?0 and y>0 and y is an odd integer, the result is ?0.
- If x is ?0 and y>0 and y is not an odd integer, the result is +0.
- If x is ?0 and y<0 and y is an odd integer, the result is ?∞.
- If x is ?0 and y<0 and y is not an odd integer, the result is +∞.
- If x<0 and x is finite and y is finite and y is not an integer, the result is NaN.
- 如果 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。
emphasis mine
强调我的
as a general rule, native functions to any language should work as described in the language specification. Sometimes this includes explicitly "undefined behavior" where it's up to the implementer to determine what the result should be, however this is not a case of undefined behavior.
作为一般规则,任何语言的本机函数都应该按照语言规范中的描述工作。有时这包括明确的“未定义行为”,由实现者决定结果应该是什么,但这不是未定义行为的情况。
回答by schmijos
It is just convention to define it as 1
, 0
or to leave it undefined
. The definition is wide spread because of the following definition:
它是将其定义为只是约定1
,0
或者离开它undefined
。由于以下定义,该定义被广泛传播:
ECMA-Script documentation says the following about pow(x,y)
:
ECMA-Script 文档说明了以下内容pow(x,y)
:
- If y is +0, the result is 1, even if x is NaN.
- If y is ?0, the result is 1, even if x is NaN.
- 如果 y 为 +0,则结果为 1,即使 x 为 NaN。
- 如果 y 为 ?0,则结果为 1,即使 x 为 NaN。
[ http://www.ecma-international.org/ecma-262/5.1/#sec-15.8.2.13]
[ http://www.ecma-international.org/ecma-262/5.1/#sec-15.8.2.13]
回答by NPE
According to Wikipedia:
根据维基百科:
In most settings not involving continuity in the exponent, interpreting 00as 1 simplifies formulas and eliminates the need for special cases in theorems.
在大多数不涉及指数连续性的设置中,将 0 0解释为 1 可以简化公式并消除对定理中特殊情况的需要。
There are several possible ways to treat 0**0
with pros and cons to each (see Wikipediafor an extended discussion).
有几种可能的方法来处理0**0
每种方法的利弊(请参阅维基百科的扩展讨论)。
The IEEE 754-2008floating point standard recommends three different functions:
在IEEE 754-2008浮点标准推荐三种不同的功能:
pow
treats0**0
as1
. This is the oldest defined version. If the power is an exact integer the result is the same as forpown
, otherwise the result is as forpowr
(except for some exceptional cases).pown
treats 0**0 as 1. The power must be an exact integer. The value is defined for negative bases; e.g.,pown(?3,5)
is?243
.powr
treats 0**0 as NaN (Not-a-Number – undefined). The value is also NaN for cases likepowr(?3,2)
where the base is less than zero. The value is defined by exp(power'×log(base)).
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)) 定义。
回答by Thomas Ahle
Donald Knuth
唐纳德·克努斯
sort of settled this debate in 1992 with the following:
1992 年通过以下方式解决了这场辩论:
And went even more into details in his paper Two Notes on Notation.
并在他的论文《关于符号的两个注释》中更详细地介绍了细节。
Basically, while we don't have 1 as the limit of f(x)/g(x)
for all not all functions f(x)
and g(x)
, it still makes combinatorics so much simpler to define 0^0=1
, and then just make special cases in the few places where you need to consider functions such as 0^x
, which are weird anyway. After all x^0
comes up a lot more often.
基本上,虽然我们没有将 1 作为f(x)/g(x)
所有函数f(x)
和的极限g(x)
,但它仍然使组合数学的定义变得如此简单0^0=1
,然后只需在需要考虑函数的少数地方进行特殊情况,例如0^x
,反正很奇怪。毕竟x^0
出现的频率要高得多。
Some of the best discussions I know of this topic (other than the Knuth paper) are:
我所知道的关于这个话题的一些最好的讨论(除了 Knuth 论文)是:
回答by Denys Séguret
When you want to know what value you should give to f(a)
when f
isn't directly computable in a
, you compute the limit of f
when x
tends towards a
.
当您想知道f(a)
在f
中不能直接计算时应该赋予什么值时a
,您可以计算f
何时x
趋向于的极限a
。
In case of x^y
, usual limits tend towards 1
when x
and y
tend to 0
, and especially x^x
tends towards 1
when x
tends to 0
.
在 的情况下x^y
,通常的限制趋向于1
何时x
和y
趋向于0
,尤其x^x
趋于趋向于1
何时x
趋向于0
。
回答by Pete Becker
The C language definition says (7.12.7.4/2):
C 语言定义说 (7.12.7.4/2):
A domain error may occur if x is zero and y is zero.
如果 x 为零且 y 为零,则可能会出现域错误。
It also says (7.12.1/2):
它还说(7.12.1/2):
On a domain error, the function returns an implementation-defined value; if the integer expression math_errhandling & MATH_ERRNO is nonzero, the integer expression errno acquires the value EDOM; if the integer expression math_errhandling & MATH_ERREXCEPT is nonzero, the ‘‘invalid'' floating-point exception is raised.
在域错误时,该函数返回一个实现定义的值;如果整数表达式 math_errhandling & MATH_ERRNO 非零,则整数表达式 errno 获取值 EDOM;如果整数表达式 math_errhandling & MATH_ERREXCEPT 非零,则引发“无效”浮点异常。
By default, the value of math_errhandling
is MATH_ERRNO
, so check errno
for the value EDOM
.
默认情况下,价值math_errhandling
就是MATH_ERRNO
,所以检查errno
的价值EDOM
。
回答by NiloCK
I'd like to disagree with some of the previous answers' assertion that it's a matter of convention or convenience (covering some special cases for various theorems, etc) that 0^0 be defined as 1 instead of 0.
我不同意之前的一些答案的断言,即 0^0 被定义为 1 而不是 0,这是一个约定或方便的问题(涵盖各种定理的一些特殊情况等)。
Exponentiation doesn't actually fit that well with our other mathematical notations, so the definition we all learn leaves room for confusion. A slightly different way of approaching it is to say that a^b (or exp(a, b), if you like) returns the value multiplicatively equivalentto multiplying some other thingby a, repeated b times.
取幂实际上并不适合我们的其他数学符号,所以我们都学习的定义留下了混淆的空间。一种稍微不同的方法是说 a^b(或 exp(a, b),如果你喜欢)返回的值乘法等效于将其他事物乘以a,重复 b 次。
When we multiply 5 by 4, 2 times, we get 80. We've multiplied 5 by 16. So 4^2 = 16.
当我们将 5 乘以 4 2 次时,我们得到 80。我们已经将 5 乘以 16。所以 4^2 = 16。
When you multiply 14 by 0, 0 times, we are left with 14. We've multiplied it 1. Hence, 0^0 = 1.
当你将 14 乘以 0 时,0 次,我们剩下 14。我们将它乘以 1。因此,0^0 = 1。
This line of thinking might also help to clarify negative and fractional exponents. 4^(-2) is a 16th, because 'negative multiplication' is division - we divide by four twice.
这种思路也可能有助于澄清负指数和分数指数。4^(-2) 是第 16 次,因为“负乘法”是除法——我们除以四两次。
a^(1/2) is root(a), because multiplying something by the root of a is half the multiplicative workas multiplying it by a itself - you would have to do it twice to multiply something by 4 = 4^1 = (4^(1/2))^2
a^(1/2) 是 root(a),因为乘以 a 的根是乘法工作的一半,因为乘以 a 本身 - 你必须做两次才能乘以 4 = 4^1 = (4^(1/2))^2
回答by Agnius Vasiliauskas
For this to understand you need to solve calculus:
为了理解这一点,你需要解决微积分:
Expanding x^x
around zero using Taylor series, we get:
x^x
使用泰勒级数在零附近展开,我们得到:
So to understand what's going on with limit when x
goes to zero,
we need to find out what's going on with second term x log(x)
, because other terms are proportional to x log(x)
raised to some power.
因此,要了解 limitx
变为零时的情况,我们需要找出第二项的情况x log(x)
,因为其他项x log(x)
与某个次幂成正比。
We need to use transformation:
我们需要使用转换:
Now after this transformation we can use L'H?pital's rule, which states that:
现在经过这个转换,我们可以使用L'H?pital 规则,它指出:
So differentiating that transformation we get:
区分这种转换,我们得到:
So we've calculated that term log(x)*x
approaches 0 when x approaches 0.
It's easy to see that other consecutive terms also approaches zero and even faster than second term.
因此,我们计算出log(x)*x
当 x 接近 0 时,该项接近 0。很容易看出,其他连续项也接近于 0,甚至比第二项更快。
So at point x=0
, series becomes 1 + 0 + 0 + 0 + ...
and thus equals to 1.
所以在点x=0
,系列变成1 + 0 + 0 + 0 + ...
并因此等于 1。