1/sqrt(x) 和 std::exp(-0.5 * std::log(x)) 之间的数值权衡
Numerical trade offs between 1/sqrt(x) and std::exp(-0.5 * std::log(x))
我遇到了一些计算
的旧代码
double y = 1 / std::sqrt(x);
使用:
constexpr double base16 = 16.0;
double log_base16 = std::log(base16);
double y = std::pow(base16, -0.5 * std::log(x) / log_base16);
本质上是:
double y = std::exp(-0.5 * std::log(x));
关于这些方法之间的数值优势(例如准确性或更有可能避免 underflow/overflow)是否有任何理由?原作者可能是这么想的
原代码确实被认为是非常顽皮的,特别是在现代 C++ 标准和 IEEE754 浮点中:
std::sqrt is required by the IEEE standard be exact. [sic.]
此外,std::pow
没有这样的要求。
因此我很想将其重写为 1 / std::sqrt(x)
,当然是测试。
我看不出有什么特别好的理由在 pow() 和 log() 方面实施 sqrt()。可能是 sqrt() 的实现中存在错误,这被用作解决方法。
总的来说,我预计此实现会更慢且更不精确。
我遇到了一些计算
的旧代码double y = 1 / std::sqrt(x);
使用:
constexpr double base16 = 16.0;
double log_base16 = std::log(base16);
double y = std::pow(base16, -0.5 * std::log(x) / log_base16);
本质上是:
double y = std::exp(-0.5 * std::log(x));
关于这些方法之间的数值优势(例如准确性或更有可能避免 underflow/overflow)是否有任何理由?原作者可能是这么想的
原代码确实被认为是非常顽皮的,特别是在现代 C++ 标准和 IEEE754 浮点中:
std::sqrt is required by the IEEE standard be exact. [sic.]
此外,std::pow
没有这样的要求。
因此我很想将其重写为 1 / std::sqrt(x)
,当然是测试。
我看不出有什么特别好的理由在 pow() 和 log() 方面实施 sqrt()。可能是 sqrt() 的实现中存在错误,这被用作解决方法。
总的来说,我预计此实现会更慢且更不精确。