为什么标准 C++ 库中没有 `int pow(int base, int exponent)`?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2398442/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 23:21:16  来源:igfitidea点击:

Why isn't `int pow(int base, int exponent)` in the standard C++ libraries?

c++mathintegerstandard-librarypow

提问by Dan O

I feel like I must just be unable to find it. Is there any reason that the C++ powfunction does not implement the "power" function for anything except floats and doubles?

我觉得我一定是找不到它。pow除了floats 和doubles之外,C++函数是否有任何原因没有实现“power”函数?

I know the implementation is trivial, I just feel like I'm doing work that should be in a standard library. A robust power function (i.e. handles overflow in some consistent, explicit way) is not fun to write.

我知道实现是微不足道的,我只是觉得我正在做应该在标准库中的工作。一个健壮的幂函数(即以某种一致的、明确的方式处理溢出)写起来并不有趣。

采纳答案by paxdiablo

As of C++11, special cases were added to the suite of power functions (and others). C++11 [c.math] /11states, after listing all the float/double/long doubleoverloads (my emphasis, and paraphrased):

从 开始C++11,特殊情况已添加到幂函数(和其他函数)套件中。C++11 [c.math] /11在列出所有float/double/long double重载(我的重点和释义)后指出:

Moreover, there shall be additional overloads sufficient to ensure that, if any argument corresponding to a doubleparameter has type doubleor an integer type, then all arguments corresponding to doubleparameters are effectively cast to double.

此外,应该有额外的重载足以确保,如果与参数对应的任何double参数具有类型double或整数类型,则与参数对应的所有double参数都被有效地强制转换为double

So, basically, integer parameters will be upgraded to doubles to perform the operation.

因此,基本上,整数参数将升级为双精度以执行操作。



Prior to C++11(which was when your question was asked), no integer overloads existed.

在此之前C++11(即在您提出问题时),不存在整数重载。

Since I was neither closely associated with the creators of Cnor C++in the days of their creation (though I amrather old), nor part of the ANSI/ISO committees that created the standards, this is necessarily opinion on my part. I'd like to think it's informedopinion but, as my wife will tell you (frequently and without much encouragement needed), I've been wrong before :-)

因为我既没有密切的关联创造者C,也不C++在他们创造的日(虽然我比较旧的),也不是创建标准ANSI / ISO委员会的组成部分,这必然是我的一部分意见。我想认为这是明智的意见,但正如我妻子会告诉你的(经常而且不需要太多鼓励),我以前错了:-)

Supposition, for what it's worth, follows.

假设,对于它的价值,如下。

I suspectthat the reason the original pre-ANSI Cdidn't have this feature is because it was totally unnecessary. First, there was already a perfectly good way of doing integer powers (with doubles and then simply converting back to an integer, checking for integer overflow and underflow before converting).

怀疑最初的 ANSIC之前没有这个功能的原因是因为它完全没有必要。首先,已经有一种非常好的整数幂的方法(使用双精度,然后简单地转换回整数,在转换之前检查整数上溢和下溢)。

Second, another thing you have to remember is that the original intent of Cwas as a systemsprogramming language, and it's questionable whether floating point is desirable in that arena at all.

其次,您必须记住的另一件事是,它的初衷C是作为一种系统编程语言,并且在该领域是否需要浮点数是值得怀疑的。

Since one of its initial use cases was to code up UNIX, the floating point would have been next to useless. BCPL, on which C was based, also had no use for powers (it didn't have floating point at all, from memory).

由于其最初的用例之一是对 UNIX 进行编码,因此浮点数几乎毫无用处。C 所基于的 BCPL 也没有使用幂(从内存中它根本没有浮点数)。

As an aside, an integral power operator would probably have been a binary operator rather than a library call. You don't add two integers with x = add (y, z)but with x = y + z- part of the language properrather than the library.

顺便说一句,整数幂运算符可能是二元运算符而不是库调用。您不会将两个整数与x = add (y, z)但与x = y + z-语言的一部分而不是库相加。

Third, since the implementation of integral power is relatively trivial, it's almost certain that the developers of the language would better use their time providing more useful stuff (see below comments on opportunity cost).

第三,由于积分功能的实现相对微不足道,几乎可以肯定语言的开发人员会更好地利用他们的时间提供更多有用的东西(请参阅下面关于机会成本的评论)。

That's also relevant for the original C++. Since the original implementation was effectively just a translator which produced Ccode, it carried over many of the attributes of C. Its original intent was C-with-classes, not C-with-classes-plus-a-little-bit-of-extra-math-stuff.

这也与原始C++. 由于原始实现实际上只是一个生成C代码的翻译器,因此它继承了C. 它的初衷是 C-with-classes,而不是 C-with-classes-plus-a-little-bit-of-extra-math-stuff。

As to why it was never added to the standards before C++11, you have to remember that the standards-setting bodies have specific guidelines to follow. For example, ANSI Cwas specifically tasked to codify existing practice, notto create a new language. Otherwise, they could have gone crazy and given us Ada :-)

至于为什么以前从未将其添加到标准中C++11,您必须记住,标准制定机构有要遵循的特定准则。例如,ANSIC专门负责编纂现有实践,而不是创建一种新语言。否则,他们可能会发疯并给我们 Ada :-)

Later iterations of that standard also have specific guidelines and can be found in the rationale documents (rationale as to why the committee made certain decisions, not rationale for the language itself).

该标准的后续迭代也有特定的指导方针,可以在理由文件中找到(关于委员会为什么做出某些决定的理由,而不是语言本身的理由)。

For example the C99rationale document specifically carries forward two of the C89guiding principles which limit what can be added:

例如,C99基本原理文件明确提出了两个C89指导原则,限制了可以添加的内容:

  • Keep the language small and simple.
  • Provide only one way to do an operation.
  • 保持语言小而简单。
  • 仅提供一种操作方式。

Guidelines (not necessarily those specificones) are laid down for the individual working groups and hence limit the C++committees (and all other ISO groups) as well.

指南(不一定是那些特定的)是为各个工作组制定的,因此也限制了C++委员会(和所有其他 ISO 组)。

In addition, the standards-setting bodies realise that there is an opportunity cost(an economic term meaning what you have to forego for a decision made) to every decision they make. For example, the opportunity cost of buying that $10,000 uber-gaming machine is cordial relations (or probably allrelations) with your other half for about six months.

此外,标准制定机构意识到他们做出的每一个决定都有机会成本(一个经济术语,意思是你必须放弃做出的决定)。例如,购买那台价值 10,000 美元的超级游戏机的机会成本是与您的另一半保持良好关系(或可能是所有关系)大约六个月。

Eric Gunnerson explains this well with his -100 points explanationas to why things aren't always added to Microsoft products- basically a feature starts 100 points in the hole so it has to add quite a bit of value to be even considered.

埃里克·冈纳森 (Eric Gunnerson) 用他的-100 分解释很好地解释了这一点,即为什么事情并不总是添加到 Microsoft 产品中 - 基本上一个功能从 100 分开始,所以它必须增加相当多的价值才能被考虑。

In other words, would you rather have a integral power operator (which, honestly, any half-decent coder could whip up in ten minutes) or multi-threading added to the standard? For myself, I'd prefer to have the latter and not have to muck about with the differing implementations under UNIX and Windows.

换句话说,您更愿意在标准中添加一个完整的幂操作符(老实说,任何一个半体面的编码器都可以在十分钟内完成)还是多线程?就我自己而言,我更喜欢后者,而不必考虑 UNIX 和 Windows 下的不同实现。

I would like to also see thousands and thousands of collection the standard library (hashes, btrees, red-black trees, dictionary, arbitrary maps and so forth) as well but, as the rationale states:

我还希望看到标准库(哈希、btree、红黑树、字典、任意映射等)成千上万的集合,但是,正如基本原理所述:

A standard is a treaty between implementer and programmer.

标准是实现者和程序员之间的条约。

And the number of implementers on the standards bodies far outweigh the number of programmers (or at least those programmers that don't understand opportunity cost). If all that stuff was added, the next standard C++would be C++215xand would probably be fully implemented by compiler developers three hundred years after that.

并且标准机构的实施者数量远远超过程序员(或至少那些不了解机会成本的程序员)的数量。如果添加了所有这些东西,那么下一个标准C++将是C++215x并且可能会在三百年后由编译器开发人员完全实现。

Anyway, that's my (rather voluminous) thoughts on the matter. If only votes were handed out bases on quantity rather than quality, I'd soon blow everyone else out of the water. Thanks for listening :-)

无论如何,这是我对此事的(相当多的)想法。如果只根据数量而不是质量来投票,我很快就会把其他所有人都吹走。谢谢收听 :-)

回答by Stephen Canon

For any fixed-width integral type, nearly all of the possible input pairs overflow the type, anyway. What's the use of standardizing a function that doesn't give a useful result for vast majority of its possible inputs?

无论如何,对于任何固定宽度的整数类型,几乎所有可能的输入对都会溢出该类型。对大多数可能的输入都没有给出有用结果的函数进行标准化有什么用?

You pretty much need to have an big integer type in order to make the function useful, and most big integer libraries provide the function.

您几乎需要有一个大整数类型才能使该函数有用,并且大多数大整数库都提供了该函数。



Edit:In a comment on the question, static_rtti writes "Most inputs cause it to overflow? The same is true for exp and double pow, I don't see anyone complaining." This is incorrect.

编辑:在对该问题的评论中,static_rtti 写道“大多数输入导致它溢出?exp 和 double pow 也是如此,我没有看到有人抱怨。” 这是不正确的。

Let's leave aside exp, because that's beside the point (though it would actually make my case stronger), and focus on double pow(double x, double y). For what portion of (x,y) pairs does this function do something useful (i.e., not simply overflow or underflow)?

让我们把 放在一边exp,因为那不是重点(尽管它实际上会使我的情况更强大),并专注于double pow(double x, double y). 这个函数对 (x,y) 对的哪一部分做了一些有用的事情(即,不仅仅是上溢或下溢)?

I'm actually going to focus only on a small portion of the input pairs for which powmakes sense, because that will be sufficient to prove my point: if x is positive and |y| <= 1, then powdoes not overflow or underflow. This comprises nearly one-quarter of all floating-point pairs (exactly half of non-NaN floating-point numbers are positive, and just less than half of non-NaN floating-point numbers have magnitude less than 1). Obviously, there are a lotof other input pairs for which powproduces useful results, but we've ascertained that it's at least one-quarter of all inputs.

我实际上只关注一小部分pow有意义的输入对,因为这足以证明我的观点:如果 x 为正且 |y| <= 1,pow则不会上溢或下溢。这包括所有浮点数对的近四分之一(恰好一半的非 NaN 浮点数是正数,只有不到一半的非 NaN 浮点数的幅度小于 1)。显然,还有很多其他输入对可以pow产生有用的结果,但我们已经确定它至少占所有输入的四分之一。

Now let's look at a fixed-width (i.e. non-bignum) integer power function. For what portion inputs does it not simply overflow? To maximize the number of meaningful input pairs, the base should be signed and the exponent unsigned. Suppose that the base and exponent are both nbits wide. We can easily get a bound on the portion of inputs that are meaningful:

现在让我们看一个固定宽度(即非 bignum)整数幂函数。对于哪一部分输入,它不会简单地溢出?为了最大化有意义的输入对的数量,基数应该是有符号的,指数应该是无符号的。假设基数和指数都是n位宽。我们可以轻松获得有意义的输入部分的界限:

  • If the exponent 0 or 1, then any base is meaningful.
  • If the exponent is 2 or greater, then no base larger than 2^(n/2) produces a meaningful result.
  • 如果指数为 0 或 1,则任何底数都是有意义的。
  • 如果指数为 2 或更大,则没有大于 2^(n/2) 的底数产生有意义的结果。

Thus, of the 2^(2n) input pairs, less than 2^(n+1) + 2^(3n/2) produce meaningful results. If we look at what is likely the most common usage, 32-bit integers, this means that something on the order of 1/1000th of one percent of input pairs do not simply overflow.

因此,在 2^(2n) 个输入对中,小于 2^(n+1) + 2^(3n/2) 会产生有意义的结果。如果我们看看最常见的用法,32 位整数,这意味着大约 1% 的输入对的 1/1000 数量级的东西不会简单地溢出。

回答by Ignacio Vazquez-Abrams

Because there's no way to represent all integer powers in an int anyways:

因为无论如何都无法在 int 中表示所有整数幂:

>>> print 2**-4
0.0625

回答by phoku

That's actually an interesting question. One argument I haven't found in the discussion is the simple lack of obvious return values for the arguments. Let's count the ways the hypthetical int pow_int(int, int)function could fail.

这其实是一个有趣的问题。我在讨论中没有找到的一个论点是参数的简单缺乏明显的返回值。让我们计算一下假设int pow_int(int, int)函数可能失败的方式。

  1. Overflow
  2. Result undefined pow_int(0,0)
  3. Result can't be represented pow_int(2,-1)
  1. 溢出
  2. 结果未定义 pow_int(0,0)
  3. 结果无法表示 pow_int(2,-1)

The function has at least 2 failure modes. Integers can't represent these values, the behaviour of the function in these cases would need to be defined by the standard - and programmers would need to be aware of how exactly the function handles these cases.

该功能至少有 2 种故障模式。整数不能表示这些值,在这些情况下函数的行为需要由标准定义 - 程序员需要知道函数如何准确地处理这些情况。

Overall leaving the function out seems like the only sensible option. The programmer can use the floating point version with all the error reporting available instead.

总体而言,将功能排除在外似乎是唯一明智的选择。程序员可以使用具有所有可用错误报告的浮点版本。

回答by enigmaticPhysicist

Short answer:

简短的回答:

A specialisation of pow(x, n)to where nis a natural number is often useful for time performance. But the standard library's generic pow()still works pretty (surprisingly!) well for this purpose and it is absolutely critical to include as little as possible in the standard C library so it can be made as portable and as easy to implement as possible. On the other hand, that doesn't stop it at all from being in the C++ standard library or the STL, which I'm pretty sure nobody is planning on using in some kind of embedded platform.

的专业化pow(x, n)的地方n是自然数往往是有用的实时性能。但是标准库的泛型pow()仍然可以很好地(令人惊讶地!)为此目的而工作,并且在标准 C 库中包含尽可能少的内容绝对是至关重要的,这样它就可以尽可能地易于移植和易于实现。另一方面,这并不能阻止它出现在 C++ 标准库或 STL 中,我很确定没有人打算在某种嵌入式平台中使用它。

Now, for the long answer.

现在,长答案。

pow(x, n)can be made much faster in many cases by specialising nto a natural number. I have had to use my own implementation of this function for almost every program I write (but I write a lot of mathematical programs in C). The specialised operation can be done in O(log(n))time, but when nis small, a simpler linear version can be faster. Here are implementations of both:

pow(x, n)在许多情况下,可以通过专门化为n自然数来加快速度。对于我编写的几乎每个程序(但我用 C 编写了很多数学程序),我不得不使用我自己的这个函数实现。专门的操作可以及时完成O(log(n)),但是当n较小时,更简单的线性版本可以更快。以下是两者的实现:


    // Computes x^n, where n is a natural number.
    double pown(double x, unsigned n)
    {
        double y = 1;
        // n = 2*d + r. x^n = (x^2)^d * x^r.
        unsigned d = n >> 1;
        unsigned r = n & 1;
        double x_2_d = d == 0? 1 : pown(x*x, d);
        double x_r = r == 0? 1 : x;
        return x_2_d*x_r;
    }
    // The linear implementation.
    double pown_l(double x, unsigned n)
    {
        double y = 1;
        for (unsigned i = 0; i < n; i++)
            y *= x;
        return y;
    }

(I left xand the return value as doubles because the result of pow(double x, unsigned n)will fit in a double about as often as pow(double, double)will.)

(我离开x了,返回值是双精度的,因为结果pow(double x, unsigned n)会和双精度一样多pow(double, double)。)

(Yes, pownis recursive, but breaking the stack is absolutely impossible since the maximum stack size will roughly equal log_2(n)and nis an integer. If nis a 64-bit integer, that gives you a maximum stack size of about 64. Nohardware has such extreme memory limitations, except for some dodgy PICs with hardware stacks that only go 3 to 8 function calls deep.)

(是的,pown是递归的,但打破堆栈是绝对不可能的,因为最大堆栈大小将大致相等log_2(n)并且n是一个整数。如果n是 64 位整数,则最大堆栈大小约为 64。没有硬件具有如此极端的内存限制,除了一些带有硬件堆栈的狡猾 PIC,这些 PIC 只能进行 3 到 8 个函数调用。)

As for performance, you'll be surprised by what a garden variety pow(double, double)is capable of. I tested a hundred million iterations on my 5-year-old IBM Thinkpad with xequal to the iteration number and nequal to 10. In this scenario, pown_lwon. glibc pow()took 12.0 user seconds, powntook 7.4 user seconds, and pown_ltook only 6.5 user seconds. So that's not too surprising. We were more or less expecting this.

至于性能,您会惊讶于花园品种pow(double, double)的能力。我在使用了 5 年的 IBM Thinkpad 上测试了 1 亿次迭代,x迭代次数n等于 10。在这种情况下,pown_l赢了。glibcpow()耗时 12.0 用户秒,pown耗时 7.4 用户秒,pown_l仅耗时 6.5 用户秒。所以这并不奇怪。我们或多或少对此有所期待。

Then, I let xbe constant (I set it to 2.5), and I looped nfrom 0 to 19 a hundred million times. This time, quite unexpectedly, glibc powwon, and by a landslide! It took only 2.0 user seconds. My powntook 9.6 seconds, and pown_ltook 12.2 seconds. What happened here? I did another test to find out.

然后,我让它x保持不变(我将其设置为 2.5),并n从 0 到 19循环了一亿次。这一次,出乎意料的是,glibcpow以压倒性优势获胜!只用了 2.0 用户秒。我用pown了 9.6 秒,用pown_l了 12.2 秒。这里发生了什么?我做了另一个测试来找出答案。

I did the same thing as above only with xequal to a million. This time, pownwon at 9.6s. pown_ltook 12.2s and glibc pow took 16.3s. Now, it's clear! glibc powperforms better than the three when xis low, but worst when xis high. When xis high, pown_lperforms best when nis low, and pownperforms best when xis high.

我做了和上面一样的事情,只是x等于一百万。这一次,pown以 9.6 秒获胜。pown_l用了 12.2 秒,glibc pow 用了 16.3 秒。现在,很清楚了!glibcpowx低时比这三个表现更好,但在x高时表现最差。当x为高时,pown_l执行时最好n为低电平,并pown执行时最好x是高的。

So here are three different algorithms, each capable of performing better than the others under the right circumstances. So, ultimately, which to use most likely depends on how you're planning on using pow, but using the right version isworth it, and having all of the versions is nice. In fact, you could even automate the choice of algorithm with a function like this:

所以这里有三种不同的算法,在适当的情况下,每种算法都能比其他算法表现得更好。因此,最终,使用哪个最有可能取决于您计划如何使用pow,但使用正确的版本值得的,并且拥有所有版本很好。事实上,您甚至可以使用如下函数自动选择算法:

double pown_auto(double x, unsigned n, double x_expected, unsigned n_expected) {
    if (x_expected < x_threshold)
        return pow(x, n);
    if (n_expected < n_threshold)
        return pown_l(x, n);
    return pown(x, n);
}

As long as x_expectedand n_expectedare constants decided at compile time, along with possibly some other caveats, an optimising compiler worth its salt will automatically remove the entire pown_autofunction call and replace it with the appropriate choice of the three algorithms. (Now, if you are actually going to attempt to usethis, you'll probably have to toy with it a little, because I didn't exactly try compilingwhat I'd written above. ;))

As long as x_expectedand n_expectedare constants decided at compile time, along with possibly some other caveats, an optimising compiler worth its salt will automatically remove the entire pown_autofunction call and replace it with the appropriate choice of the three algorithms. (现在,如果您真的要尝试使用它,您可能需要稍微玩弄它,因为我并没有完全尝试编译我上面写的内容。;))

On the other hand, glibc powdoes workand glibc is big enough already. The C standard is supposed to be portable, including to various embedded devices(in fact embedded developers everywhere generally agree that glibc is already too big for them), and it can't be portable if for every simple math function it needs to include every alternative algorithm that mightbe of use. So, that's why it isn't in the C standard.

另一方面,glibcpow确实有效并且 glibc 已经足够大了。C 标准应该是可移植的,包括各种嵌入式设备(事实上​​,各地的嵌入式开发人员普遍认为 glibc 对他们来说已经太大了),如果对于每个简单的数学函数,它需要包含每个可能有用的替代算法。所以,这就是为什么它不在 C 标准中。

footnote: In the time performance testing, I gave my functions relatively generous optimisation flags (-s -O2) that are likely to be comparable to, if not worse than, what was likely used to compile glibc on my system (archlinux), so the results are probably fair. For a more rigorous test, I'd have to compile glibc myself and I reeeallydon't feel like doing that. I used to use Gentoo, so I remember how long it takes, even when the task is automated. The results are conclusive (or rather inconclusive) enough for me. You're of course welcome to do this yourself.

脚注:在时间性能测试中,我给了我的函数相对慷慨的优化标志 ( -s -O2),这些标志很可能与在我的系统 (archlinux) 上编译 glibc 可能使用的东西相媲美,甚至更糟,所以结果可能是公平的。对于更严格的测试,我不得不编译glibc的自己,我reeeally不喜欢这样做。我以前用过 Gentoo,所以我记得需要多长时间,即使任务是自动化的。结果对我来说是决定性的(或者说是不确定的)。当然,欢迎你自己做这件事。

Bonus round: A specialisation of pow(x, n)to all integers is instrumentalif an exact integer output is required, which does happen. Consider allocating memory for an N-dimensional array with p^N elements. Getting p^N off even by one will result in a possibly randomly occurring segfault.

奖励回合:如果需要精确的整数输出,则pow(x, n)对所有整数的特化是有用的,这确实发生了。考虑为具有 p^N 个元素的 N 维数组分配内存。即使将 p^N 减一也会导致可能随机发生的段错误。

回答by Bo Persson

One reason for C++ to not have additional overloads is to be compatible with C.

C++ 没有额外重载的原因之一是与 C 兼容。

C++98 has functions like double pow(double, int), but these have been removed in C++11 with the argument that C99 didn't include them.

C++98 有类似 的函数double pow(double, int),但这些函数在 C++11 中被删除了,因为 C99 没有包含它们。

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3286.html#550

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3286.html#550

Getting a slightly more accurate result also means getting a slightly differentresult.

获得稍微更准确的结果也意味着获得稍微不同的结果。

回答by Morwenn

The World is constantly evolving and so are the programming languages. The fourth part of the C decimal TR1 adds some more functions to <math.h>. Two families of these functions may be of interest for this question:

世界在不断发展,编程语言也在不断发展。C 十进制 TR1的第四部分<math.h>. 这些函数的两个系列可能对这个问题感兴趣:

  • The pownfunctions, that takes a floating point number and an intmax_texponent.
  • The powrfunctions, that takes two floating points numbers (xand y) and compute xto the power ywith the formula exp(y*log(x)).
  • pown功能,需要一个浮点数和一个intmax_t指数。
  • 这些powr函数采用两个浮点数 (xy) 并用公式计算x幂。yexp(y*log(x))

It seems that the standard guys eventually deemed these features useful enough to be integrated in the standard library. However, the rational is that these functions are recommended by the ISO/IEC/IEEE 60559:2011standard for binary and decimal floating point numbers. I can't say for sure what "standard" was followed at the time of C89, but the future evolutions of <math.h>will probably be heavily influenced by the future evolutions of the ISO/IEC/IEEE 60559standard.

似乎标准人员最终认为这些功能足够有用,可以集成到标准库中。然而,合理的是这些函数是ISO/IEC/IEEE 60559:2011标准推荐的二进制和十进制浮点数。我不能确定在 C89 的时候遵循什么“标准”,但是未来的演变<math.h>可能会受到ISO/IEC/IEEE 60559标准未来演变的严重影响。

Note that the fourth part of the decimal TR won't be included in C2x (the next major C revision), and will probably be included later as an optional feature. There hasn't been any intent I know of to include this part of the TR in a future C++ revision.

请注意,十进制 TR 的第四部分不会包含在 C2x(下一个主要 C 修订版)中,并且可能会在稍后作为可选功能包含在内。据我所知,没有任何意图将 TR 的这一部分包含在未来的 C++ 修订版中。



1 You can find some work-in-progress documentation here.

1 您可以在此处找到一些正在进行的文档。

回答by Ben Voigt

Perhaps because the processor's ALU didn't implement such a function for integers, but there is such an FPU instruction (as Stephen points out, it's actually a pair). So it was actually faster to cast to double, call pow with doubles, then test for overflow and cast back, than to implement it using integer arithmetic.

也许是因为处理器的 ALU 没有为整数实现这样的函数,但是有这样的 FPU 指令(正如 Stephen 指出的,它实际上是一对)。因此,与使用整数算术实现它相比,转换为双精度,使用双精度调用 pow,然后测试溢出并返回实际上更快。

(for one thing, logarithms reduce powers to multiplication, but logarithms of integers lose a lot of accuracy for most inputs)

(一方面,对数降低了乘法的能力,但整数的对数对大多数输入失去了很多准确性)

Stephen is right that on modern processors this is no longer true, but the C standard when the math functions were selected (C++ just used the C functions) is now what, 20 years old?

斯蒂芬是对的,在现代处理器上这不再正确,但是选择数学函数时的 C 标准(C++ 只使用 C 函数)现在是什么,20 岁?

回答by serg06

Here's a really simple O(log(n))implementation of pow() that works for any numeric types, including integers:

这是 pow()的一个非常简单的O(log(n))实现,适用于任何数字类型,包括整数

template<typename T>
static constexpr inline T pown(T x, unsigned p) {
    T result = 1;

    while (p) {
        if (p & 0x1) {
            result *= x;
        }
        x *= x;
        p >>= 1;
    }

    return result;
}

It's better than enigmaticPhysicist's O(log(n)) implementation because it doesn't use recursion.

它比 enigmaticPhysicist 的 O(log(n)) 实现更好,因为它不使用递归。

It's also almost always faster than his linear implementation (as long as p > ~3) because:

它也几乎总是比他的线性实现更快(只要 p > ~3),因为:

  • it doesn't require any extra memory
  • it only does ~1.5x more operations per loop
  • it only does ~1.25x more memory updates per loop
  • 它不需要任何额外的内存
  • 每个循环只执行约 1.5 倍的操作
  • 每个循环只进行约 1.25 倍的内存更新

回答by Dima Pasechnik

As a matter of fact, it does.

事实上,确实如此。

Since C++11 there is a templated implementation of pow(int, int)--- and even more general cases, see (7) in http://en.cppreference.com/w/cpp/numeric/math/pow

由于 C++11 有一个pow(int, int)--- 甚至更一般情况的模板化实现,请参阅http://en.cppreference.com/w/cpp/numeric/math/pow 中的(7)



EDIT: purists may argue this is not correct, as there is actually "promoted" typing used. One way or another, one gets a correct intresult, or an error, on intparameters.

编辑:纯粹主义者可能会争辩说这是不正确的,因为实际上使用了“提升”的打字方式。以一种或另一种方式int,可以在int参数上获得正确的结果或错误。