【发布时间】: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<double>::has_quiet_NaN并根据该信息采取行动。但我想大多数人现在都会接受 IEEE754 合规性。您还有什么其他不同的想法吗? -
如果您确实关心效率,请注意使用 NaN 会严重损害 x86 和 x64 架构的性能。每次出现 NaN 或在寄存器中被触摸时,FPU 都会停顿大约 20 个周期(我猜是因为它触发了微编码子程序或其他东西)。在数学繁重的应用程序中,这可能会增加巨大的成本。我曾经看到一个配置文件,其中 10% 的 CPU 时间都花在了 NaN 停顿上。