【问题标题】:How to efficiently implement infinity and minus infinity supporting arithmetic in C++?如何在 C++ 中有效地实现支持算术的无穷大和负无穷大?
【发布时间】:2012-05-16 04:19:12
【问题描述】:

简单的解决方案是:

class Number
{
public: 
    bool isFinite();
    bool isPositive();
    double value();

    ...

private:
    double value_;
    bool isFinite_;
    bool isPositive_;

    ...
};

让我担心的是效率:

来自有效的 C++:改进程序和设计的 55 种特定方法(第 3 版),作者:Scott Meyers:

即使小对象有廉价的复制构造函数,也可以 是性能问题。一些编译器处理内置和用户定义 类型不同,即使它们具有相同的底层 表示。例如,一些编译器拒绝放置对象 只包含一个双精度的寄存器,即使他们很高兴 定期在那里放置裸体双打。当那种事 发生时,您最好通过引用传递此类对象, 因为编译器肯定会放置指针(实现 引用)到寄存器中。

有没有办法绕过效率问题?例如一个使用一些汇编语言魔法的库?

【问题讨论】:

  • 您是否尝试过查看程序集以查看您的编译器是否正在生成您提到的脑死代码?
  • 我很想知道,在您解决了性能问题之后,当操作数为无穷大时,您的算术运算会做什么!
  • 我是 C++ 初学者,对汇编语言几乎一无所知。这样的事情超出了我现在的能力。我只是希望有一个众所周知的解决方案。
  • @cheeken 有些操作是定义好的,en.wikipedia.org/wiki/Extended_real_number_line,有些会返回NaN,或者抛出异常。这样的算术例如在 Mathematica 中实现
  • @MartinDrozdik 实际上,对于操作的子集,“无限操作”可以是确定性的。但其中许多不是,涉及它们的计算集似乎会迅速转变为NaN 的池。对我来说,这引出了一个问题:这是正确的方法吗?

标签: c++ math


【解决方案1】:

几乎没有理由为 double 实现 Number 类。 double 格式已经实现了 Infinity、NaN 和 signage 作为原始基本 double 类型的一部分。

其次,你应该先写代码,以正确为目标,然后再尝试优化,这时候你可以考虑分解出特定的数据结构并重写代码和算法。

现代编译器在编写优质代码方面通常非常高效,并且通常比大多数人类程序员做得更好。

【讨论】:

  • 全部为真;但是当您预先知道程序必须很好地扩展(例如多声道声音分析包)时,您最好意识到潜在的瓶颈。
  • @xtofl -- 那么我建议只使用#define MACOS 和模板类进行编程,并避免编译器无法展开的任何数据结构。
  • 谢谢索伦!我从来没有意识到这一点。它似乎可以与各种基本数学函数按预期工作。但这是标准 C++ 还是 gcc 编译器的创建者作为奖励提供的东西?
【解决方案2】:

对于您的 特定 示例,我将按原样使用双打而不是在课堂上使用。它们非常适合和定义用于处理无穷大。

在更一般的意义上,您应该使用微不足道的解决方案,并且只在(或者更有可能,如果)它成为问题时才担心性能。

这意味着对它进行编码并在您将要使用它的许多场景中对其进行测试。

如果它仍然在您的性能要求范围内执行,请不要担心尝试对其进行优化。你应该一些性能要求稍微具体一点,“我希望它运行得尽可能快”:-)

请记住,效率并不总是意味着“尽可能快,不计成本”。这意味着在不必牺牲其他东西(如可读性或可维护性)的情况下实现您的目标。

如果你进行一个让用户等待 0.1 秒的完整操作并将其优化到快十倍的程度,用户根本不会注意到这一点(我说“完成”,因为显然,用户 如果在没有某种临时结果的情况下进行一万次,会发现差异。

记住,衡量,不要猜测!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-19
    • 2013-11-29
    • 2017-08-19
    • 2022-08-12
    • 1970-01-01
    • 2020-01-07
    • 2012-10-08
    相关资源
    最近更新 更多