何时使用' std::hypot(x,y) '而不是' std::sqrt(x*x + y*y) '
When to use `std::hypot(x,y)` over `std::sqrt(x*x + y*y)`
std::hypot
的文档说:
计算x和y平方和的平方根,在计算的中间阶段没有不当的溢出或下溢。
我很难设想一个测试用例,其中std::hypot
应该在平凡的sqrt(x*x + y*y)
上使用。
下面的测试显示std::hypot
大约比原始计算慢20倍。
#include <iostream>
#include <chrono>
#include <random>
#include <algorithm>
int main(int, char**) {
std::mt19937_64 mt;
const auto samples = 10000000;
std::vector<double> values(2 * samples);
std::uniform_real_distribution<double> urd(-100.0, 100.0);
std::generate_n(values.begin(), 2 * samples, [&]() {return urd(mt); });
std::cout.precision(15);
{
double sum = 0;
auto s = std::chrono::steady_clock::now();
for (auto i = 0; i < 2 * samples; i += 2) {
sum += std::hypot(values[i], values[i + 1]);
}
auto e = std::chrono::steady_clock::now();
std::cout << std::fixed <<std::chrono::duration_cast<std::chrono::microseconds>(e - s).count() << "us --- s:" << sum << std::endl;
}
{
double sum = 0;
auto s = std::chrono::steady_clock::now();
for (auto i = 0; i < 2 * samples; i += 2) {
sum += std::sqrt(values[i]* values[i] + values[i + 1]* values[i + 1]);
}
auto e = std::chrono::steady_clock::now();
std::cout << std::fixed << std::chrono::duration_cast<std::chrono::microseconds>(e - s).count() << "us --- s:" << sum << std::endl;
}
}
所以我要求指导,什么时候我必须使用std::hypot(x,y)
来获得比更快的std::sqrt(x*x + y*y)
正确的结果。
澄清:我正在寻找x
和y
是浮点数时适用的答案。即比较:
double h = std::hypot(static_cast<double>(x),static_cast<double>(y));
:
double xx = static_cast<double>(x);
double yy = static_cast<double>(y);
double h = std::sqrt(xx*xx + yy*yy);
答案在你引用的文档中
计算x和y平方和的平方根,在计算的中间阶段没有过度的溢出或下溢。
如果x*x + y*y
溢出,那么如果您手动执行计算,您将得到错误的答案。但是,如果使用std::hypot
,则可以保证中间计算不会溢出。
你可以在这里看到一个差异的例子。
如果您正在处理的数字不会超出您的平台的相关表示,那么您可以愉快地使用朴素版本。
相关文章:
- 使用std::multimap迭代器创建std::list
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 如何导出包含具有"std::unique_ptr"值的"std::map"属性的
- 从持续时间构造std::chrono::system_clock::time_point
- std::具有相同基类的类的变体
- std::向量与传递值的动态数组
- 使用std::vector的OpenCL矩阵乘法
- std::map<struct,struct>::find 找不到匹配项,但是如果我循环通过 begin() 到 end(),我在那里看到匹配项
- std::condition_variable::wait()如何评估给定的谓词
- 如何获取std::result_of函数的返回类型
- std::原子加载和存储都需要吗
- 如果我重新定义 sqrt 函数,为什么使用 std::sqrt 失败?
- How can I std::sqrt(boost::lambda::placeholder1_type)?
- 1/sqrt(x) 和 std::exp(-0.5 * std::log(x)) 之间的数值权衡
- 为什么 GCC 不能优化出 'std::sqrt'?
- 为什么std::sqrt()在C++中不能正确处理双数据
- std::sqrt()函数是如何工作的
- 何时使用' std::hypot(x,y) '而不是' std::sqrt(x*x + y*y) '