【问题标题】:C/C++ NaN or boolean?C/C++ NaN 还是布尔值?
【发布时间】:2015-09-24 19:12:37
【问题描述】:

我必须缓存一个双精度值。使用后应作废。两种选择

一种是加布尔标志,缓存值好的时候true,使用的时候设置为false,标志为假的时候重新计算再填充。

第二个更有趣 - 我可以将其保留为双精度值并将 NaN 用作无效/需要重新计算标志。

double get() const {
    if (!isnan(_value)) {
        double t = _value;
        _value = std::numeric_limits<double>::quiet_NaN;
        return t;
    }
}

有反对意见吗?对效率有什么想法吗?

【问题讨论】:

  • 这是 C 题还是 C++ 题?两种语言的答案完全不同。
  • 关键问题:NaN 是否曾经是设置缓存的合理值?这始终是使用标志值的关键问题 - 如果在正常操作期间可以将值设置为标志,那么您将面临一个真正令人头疼的问题。
  • “效率”可能不如算法的可理解性、可靠性和解决方案的适用性那么重要。
  • @DavidSchwartz 尽管我不喜欢混淆 C 和 C++,但我看不出这里的答案会完全不同。我能看到的唯一方面是 C++ 将允许我在编译时测试 std::numeric_limits&lt;double&gt;::has_quiet_NaN 并根据该信息采取行动。但我想大多数人现在都会接受 IEEE754 合规性。您还有什么其他不同的想法吗?
  • 如果您确实关心效率,请注意使用 NaN 会严重损害 x86 和 x64 架构的性能。每次出现 NaN 或在寄存器中被触摸时,FPU 都会停顿大约 20 个周期(我猜是因为它触发了微编码子程序或其他东西)。在数学繁重的应用程序中,这可能会增加巨大的成本。我曾经看到一个配置文件,其中 10% 的 CPU 时间都花在了 NaN 停顿上。

标签: c++ fpu


【解决方案1】:

使用布尔值,否则当您计算的双精度实际上是 NaN(由于计算)时,您最终会遇到一些有趣的问题/错误。如果您依赖 NaN 作为“我已使用该值”的信号,那么您将无法区分“有效”未使用的 NaN。

更不用说这种语义过载会导致您代码的未来读者(甚至是几个月后的您自己)在试图破译这种巧妙的用法时摸不着头脑。 ;-)

一般来说,重载变量的含义是一种不好的做法。起初它可能看起来很可爱,但它不可避免地会在未来造成更多伤害。

效率而言 - 我真的建议您先衡量,然后再担心优化。我敢打赌,运行测试后,您会发现速度差异远低于 CPU 温度波动引起的性能噪音。

【讨论】:

  • 是的,这是一个问题。如果重新填充代码产生 NaN,事情可能会变得有趣......
  • 一个非常有效的问题,也是您在生产中真正不想处理的问题;-)
【解决方案2】:

我怀疑效率会有所不同,但是带有布尔标志的代码会更具可读性:

double get() const {
    if (!_cached)
        _value = recalculate();
    _cached = !_cached;
    return _value;
}

【讨论】:

    【解决方案3】:

    我认为值得指出的是 nan 可能是更有效的解决方案,最大的优势是您使用的内存比使用标志少(由于对齐,其开销可能超过每双精度 1 个字节)。这意味着如果您需要读取大量内存,它也可能会更快。

    另外需要指出的是,IEEE nans 可以有不同的值。它们的指数必须全为 1,但尾数可以是除全零以外的任何值。这意味着您可以使用“特殊” nan 来区分计算结果产生的 nan,或者如果您需要具有两个以上状态的标志,甚至可以使用不同类型的 nan。

    【讨论】:

    • 这种方法的问题是,唯一可以检查的标准函数是isnan() 和朋友。如果真的有不同的 NaN 模式要使用,我必须写 is_that_NaN()is_it_another_NaN() 等。但是感谢您的回答
    • @SeverinPappadeux,这是真的,但它是一个非常短的函数。 memcmp(&my_double, &my_special_nan, sizeof(double)) !=0 就可以了。
    猜你喜欢
    • 2013-08-05
    • 2023-03-02
    • 1970-01-01
    • 2012-06-05
    • 2011-03-17
    • 2011-12-22
    • 1970-01-01
    • 2011-03-28
    • 2018-12-13
    相关资源
    最近更新 更多