C/C++ NaN 还是布尔值?
C/C++ NaN or boolean?
我必须保留一个双值缓存。使用后应作废。两种选择
一个是添加boolean flag,true
缓存值好的时候,使用的时候设置为false
,flag为false的时候,重新计算重新填充。
第二个更有趣 - 我可以将它保留为双精度值并使用 NaN 作为 invalid/need 来重新计算标志。
double get() const {
if (!isnan(_value)) {
double t = _value;
_value = std::numeric_limits<double>::quiet_NaN;
return t;
}
}
有反对意见吗?对效率有什么想法吗?
使用布尔值,否则当您计算的双精度结果实际上是 NaN(由于计算)时,您最终会得到一些有趣的 problems/bugs。如果您依赖 NaN 作为 "I have used that value" 的信号,那么您将无法区分 "valid" 未使用的 NaN。
更不用说这种语义超载会导致您的代码的未来 reader(甚至是几个月后的您自己)为了破译这种巧妙的用法而挠头。 ;-)
一般来说,重载变量的含义是一种不好的做法。乍一看它可能看起来很可爱,但它不可避免地会造成更多伤害。
就 效率 而言 - 我真的建议您先进行衡量,然后再考虑优化。我敢打赌,一旦你 运行 测试,你会发现速度差异远低于 CPU 温度波动引起的性能噪音。
我认为值得指出的是,nan 可能是更有效的解决方案,最大的优势是您使用的内存比标志少(其开销可能超过 1 个字节/双精度,因为对齐)。这意味着如果您需要读取大量内存,它也可能会更快。
另一件需要指出的事情是 IEEE nans 可以有不同的值。它们的指数必须全为 1,但尾数可以是除全零以外的任何值。这意味着您可以使用 "special" nan 来区分计算结果产生的 nan,或者如果您需要具有两个以上状态的标志,甚至可以使用不同种类的 nan。
我怀疑效率会有所不同,但带有布尔标志的代码会更具可读性:
double get() const {
if (!_cached)
_value = recalculate();
_cached = !_cached;
return _value;
}
我必须保留一个双值缓存。使用后应作废。两种选择
一个是添加boolean flag,true
缓存值好的时候,使用的时候设置为false
,flag为false的时候,重新计算重新填充。
第二个更有趣 - 我可以将它保留为双精度值并使用 NaN 作为 invalid/need 来重新计算标志。
double get() const {
if (!isnan(_value)) {
double t = _value;
_value = std::numeric_limits<double>::quiet_NaN;
return t;
}
}
有反对意见吗?对效率有什么想法吗?
使用布尔值,否则当您计算的双精度结果实际上是 NaN(由于计算)时,您最终会得到一些有趣的 problems/bugs。如果您依赖 NaN 作为 "I have used that value" 的信号,那么您将无法区分 "valid" 未使用的 NaN。
更不用说这种语义超载会导致您的代码的未来 reader(甚至是几个月后的您自己)为了破译这种巧妙的用法而挠头。 ;-)
一般来说,重载变量的含义是一种不好的做法。乍一看它可能看起来很可爱,但它不可避免地会造成更多伤害。
就 效率 而言 - 我真的建议您先进行衡量,然后再考虑优化。我敢打赌,一旦你 运行 测试,你会发现速度差异远低于 CPU 温度波动引起的性能噪音。
我认为值得指出的是,nan 可能是更有效的解决方案,最大的优势是您使用的内存比标志少(其开销可能超过 1 个字节/双精度,因为对齐)。这意味着如果您需要读取大量内存,它也可能会更快。
另一件需要指出的事情是 IEEE nans 可以有不同的值。它们的指数必须全为 1,但尾数可以是除全零以外的任何值。这意味着您可以使用 "special" nan 来区分计算结果产生的 nan,或者如果您需要具有两个以上状态的标志,甚至可以使用不同种类的 nan。
我怀疑效率会有所不同,但带有布尔标志的代码会更具可读性:
double get() const {
if (!_cached)
_value = recalculate();
_cached = !_cached;
return _value;
}