提问人:keith 提问时间:2/6/2017 更新时间:2/6/2017 访问量:312
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));
在方法之间的数值优势(例如准确性或更有可能避免下溢/溢流)方面是否有任何理由?原作者可能是这么认为的。
答:
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
评论
constexpr