何时使用 std::hypot(x,y) 而不是 std::sqrt(x*x + y*y)
When to use `std::hypot(x,y)` over `std::sqrt(x*x + y*y)`
documentation of std::hypot
说:
Computes the square root of the sum of the squares of x and y, without undue overflow or underflow at intermediate stages of the computation.
我很难构思一个测试用例,其中 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
是浮点数时适用的答案。 IE。比较:
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);
答案在您引用的文档中
Computes the square root of the sum of the squares of x and y, without undue overflow or underflow at intermediate stages of the computation.
如果x*x + y*y
溢出,那么如果您手动进行计算,您将得到错误的答案。但是,如果使用std::hypot
,则保证中间计算不会溢出。
您可以看到这种差异的示例 here。
如果您使用的数字不会溢出您平台的相关表示,您可以愉快地使用原始版本。
documentation of std::hypot
说:
Computes the square root of the sum of the squares of x and y, without undue overflow or underflow at intermediate stages of the computation.
我很难构思一个测试用例,其中 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
是浮点数时适用的答案。 IE。比较:
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);
答案在您引用的文档中
Computes the square root of the sum of the squares of x and y, without undue overflow or underflow at intermediate stages of the computation.
如果x*x + y*y
溢出,那么如果您手动进行计算,您将得到错误的答案。但是,如果使用std::hypot
,则保证中间计算不会溢出。
您可以看到这种差异的示例 here。
如果您使用的数字不会溢出您平台的相关表示,您可以愉快地使用原始版本。