C++ 为什么不是';标准C+中的t`int pow(int base,int exponent)`+;图书馆?
我觉得我一定是找不到了。是否有任何理由,C++ <代码> POW<代码>函数不实现除“代码>浮点< /Cult> s和<代码>双< /Calp>S.以外的任何“幂”函数?C++ 为什么不是';标准C+中的t`int pow(int base,int exponent)`+;图书馆?,c++,math,integer,standard-library,pow,C++,Math,Integer,Standard Library,Pow,我觉得我一定是找不到了。是否有任何理由,C++ POW函数不实现除“代码>浮点< /Cult> s和双< /Calp>S.以外的任何“幂”函数? 我知道实现是微不足道的,我只是觉得我在做应该在标准库中进行的工作。健壮的幂函数(即以某种一致、明确的方式处理溢出)编写起来并不有趣。因为无论如何都无法在int中表示所有整数幂: >>> print 2**-4 0.0625 对于任何固定宽度的整数类型,几乎所有可能的输入对都会溢出该类型。如果一个函数的绝大多数可能输入都不能给出有用
我知道实现是微不足道的,我只是觉得我在做应该在标准库中进行的工作。健壮的幂函数(即以某种一致、明确的方式处理溢出)编写起来并不有趣。因为无论如何都无法在int中表示所有整数幂:
>>> print 2**-4
0.0625
对于任何固定宽度的整数类型,几乎所有可能的输入对都会溢出该类型。如果一个函数的绝大多数可能输入都不能给出有用的结果,那么标准化该函数有什么用呢 为了使函数有用,您几乎需要一个大整数类型,大多数大整数库都提供了该函数
编辑:在对该问题的评论中,static\u rtti写道“大多数输入导致它溢出?exp和double pow也是如此,我没有看到任何人抱怨。”这是不正确的 让我们把
exp
放在一边,因为这与重点无关(尽管这实际上会使我的案例更加有力),我们将重点放在double-pow(double-x,double-y)
。对于(x,y)对的哪个部分,该函数做了有用的事情(即,不只是溢出或下溢)
实际上,我将只关注输入对的一小部分,
pow
对其有意义,因为这将足以证明我的观点:如果x为正且| y |,可能是因为处理器的ALU没有实现这样一个整数函数,但有这样一个FPU指令(正如Stephen所指出的,它实际上是一对)。因此,实际上转换为double、使用double调用pow、然后测试溢出和回滚比使用整数算法实现更快
(一方面,对数降低了乘法的幂次,但对于大多数输入,整数的对数会失去很多精度)
Stephen说得对,在现代处理器上,这不再是事实,但选择数学函数时的C标准(C++只是使用C函数)现在已经有20年的历史了?到
C++11
,幂函数套件(和其他)中添加了特殊情况。C++11[C.math]/11
在列出所有的浮点/双精度/长双精度
重载(我的重点和释义)之后声明:
此外,应具有足够的额外重载,以确保如果与double
参数对应的任何参数具有类型double
或整数类型,则与double
参数对应的所有参数都有效地转换为double
因此,基本上,整数参数将升级为双倍以执行该操作
在
C++11
之前(当您被问及问题时),不存在整数重载
由于我与C
和C++
的创作者(尽管我已经很老了)都没有密切的联系,也不是创建标准的ANSI/ISO委员会的一员,这必然是我的观点。我想这是知情的观点,但正如我妻子告诉你的那样(经常而且不需要太多鼓励),我以前就错了:-)
假设,不管它值多少钱,随之而来
我怀疑最初的前ANSIC
没有这个功能的原因是因为它完全没有必要。首先,已经有一种非常好的方法可以进行整数幂运算(使用双倍运算,然后简单地转换回整数,在转换前检查整数上溢和下溢)
其次,您必须记住的另一件事是,C
的初衷是作为一种系统编程语言,而浮点运算在这一领域是否可取值得怀疑
由于它最初的一个用例是编写UNIX代码,因此浮点几乎是无用的。C语言所基于的BCPL也没有使用powers(它从内存中根本没有浮点)
另一方面,整数幂运算符可能是二进制运算符,而不是库调用。您不会用x=add(y,z)
添加两个整数,而是用x=y+z
添加两个整数,这是语言本身的一部分,而不是库
第三,由于integral-power的实现相对简单,几乎可以肯定,该语言的开发人员会更好地利用他们的时间提供更多有用的东西(参见下面关于机会成本的评论)
这也与原始的C++
相关。由于原始实现实际上只是一个生成C
代码的翻译器,它继承了C
的许多属性。它的初衷是C-with-classes,而不是C-with-classes-plus-a-bit-extra-math-stuff
至于为什么在C++11
之前从未将其添加到标准中,你必须记住,标准制定机构有具体的指导方针要遵循。例如,ANSIC
专门负责编纂现有实践,而不是创建新的语言。否则,他们可能会发疯,给我们Ada:-)
该标准的后续版本也有具体的指南,可以在基本原理文件中找到(关于委员会为什么做出某些决定的基本原理,而不是语言本身的基本原理)
例如,C99
基本原理文件具体继承了C89
指导原则中的两项,这两项原则限制了可以添加的内容:
- 保持语言简洁明了。
- 仅提供一种执行操作的方法
5^-2 = 1/25
// 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;
}
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);
}
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;
}