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),当然是测试。

参考:http://en.cppreference.com/w/cpp/numeric/math/sqrt

我看不出有什么特别好的理由在 pow() 和 log() 方面实施 sqrt()。可能是 sqrt() 的实现中存在错误,这被用作解决方法。

总的来说,我预计此实现会更慢且更不精确。