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

新手上路,请多包涵

我觉得我一定是找不到它。除了 float s 和 double s 之外,C++ pow 函数没有实现“power”函数吗?

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

原文由 Dan O 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 817
2 个回答

C++11 ,特殊情况被添加到幂函数(和其他)套件中。 C++11 [c.math] /11 在列出所有 float/double/long double 重载(我的重点,并转述)之后:

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

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


C++11 之前(这是问您的问题时),不存在整数重载。

因为在 CC++ 的创建者(尽管 我已经 相当老了)的创建者中,我既不是密切相关的,也不是创建标准,这必然是我的观点。我想认为这是 明智 的意见,但是,正如我妻子会告诉你的(经常而且不需要太多鼓励),我以前错了:-)

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

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

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

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

顺便说一句,积分幂运算符可能是二元运算符而不是库调用。您不要使用 x = add (y, z) 而是使用 x = y + z 添加两个整数 - 是 语言本身 而不是库的一部分。

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

这也与原始 C++ 相关。由于最初的实现实际上只是一个产生 C 代码的翻译器,它继承了 C 的许多属性。它最初的意图是 C-with-classes,而不是 C-with-classes-plus-a-little-bit-of-extra-math-stuff。

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

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

例如 C99 基本原理文件特别继承了 C89 指导原则中的两个限制可以添加的内容:

  • 保持语言小而简单。

  • 只提供一种方法来进行操作。

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

此外,标准制定机构意识到他们做出的每一个决定都存在 _机会成本_(一个经济术语,意思是你必须为做出决定而放弃的东西)。例如,购买价值 10,000 美元的超级游戏机的机会成本是与另一半建立约 6 个月的友好关系(或可能是 所有 关系)。

Eric Gunnerson 用他的 -100 分解释 很好地解释了为什么不总是将东西添加到 Microsoft 产品中 - 基本上,一个功能从 100 分开始,所以它必须增加相当多的价值才能被考虑。

换句话说,您更愿意在标准中添加一个完整的电源运算符(老实说,任何半体面的程序员都可以在十分钟内完成)还是多线程?就我自己而言,我更喜欢后者,而不必纠结于 UNIX 和 Windows 下的不同实现。

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

标准是实现者和程序员之间的协议。

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

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

原文由 paxdiablo 发布,翻译遵循 CC BY-SA 4.0 许可协议

这是 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;
}

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

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

  • 它不需要任何额外的内存
  • 每个循环只执行约 1.5 倍的操作
  • 每次循环它只会增加约 1.25 倍的内存更新

原文由 serg06 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题