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))

提问人:keith 提问时间:2/6/2017 更新时间:2/6/2017 访问量:312

问:

我遇到过一些计算

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));

在方法之间的数值优势(例如准确性或更有可能避免下溢/溢流)方面是否有任何理由?原作者可能是这么认为的。

C++ C++11 数字 浮点精度

评论

1赞 Potatoswatter 2/6/2017
它可以多大? 2011年标准化。constexpr
0赞 keith 2/6/2017
@Potatoswatte,我清理了语法,使示例尽可能清晰。

答:

2赞 Bathsheba 2/6/2017 #1

原始代码确实被认为是非常顽皮的,尤其是在现代C++标准和浮点IEEE754:

确切地说,std::sqrt 是 IEEE 标准所要求的。[原文如此]

此外,没有这样的要求。std::pow

因此,我很想把它重写为 ,当然是测试。1 / std::sqrt(x)

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

评论

0赞 MSalters 2/6/2017
请注意,“精确”是有代价的。从理论上讲,替代代码可能更快。也就是说,这是非常理论化的。唯一的快速对数是以 2 为底数及其幂,幂也是如此。 可能比旧代码快很多。2^(log2(x)/2)
0赞 Yakk - Adam Nevraumont 2/6/2017
@MSalters 当然,异或会更快,但对于大多数值来说,准确性会降低。
0赞 MSalters 2/6/2017
@Yakk:简写std::exp2(std::log2(x)/2))
1赞 Yakk - Adam Nevraumont 2/6/2017
@MSalters 不,是 xor 在C++。跟上!;)^
0赞 Paul Floyd 2/6/2017 #2

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

一般来说,我预计这种实现会更慢、更不精确。

评论

1赞 MSalters 2/6/2017
鉴于,我很确定我们可以假设1 / std::sqrt(x)x>0