简体   繁体   English

何时使用`std :: hypot(x,y)`而不是`std :: sqrt(x * x + y * y)`

[英]When to use `std::hypot(x,y)` over `std::sqrt(x*x + y*y)`

The documentation of std::hypot says that: 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. 计算x和y的平方和的平方根,在计算的中间阶段没有过度溢出或下溢。

I struggle to conceive a test case where std::hypot should be used over the trivial sqrt(x*x + y*y) . 我很难设想一个测试用例,其中std::hypot应该用于普通的sqrt(x*x + y*y)

The following test shows that std::hypot is roughly 20x slower than the naive calculation. 以下测试表明, 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;
    }
}

So I'm asking for guidance, when must I use std::hypot(x,y) to obtain correct results over the much faster std::sqrt(x*x + y*y) . 所以我要求指导,何时我必须使用std::hypot(x,y)来获得更快的std::sqrt(x*x + y*y)正确结果。

Clarification: I'm looking for answers that apply when x and y are floating point numbers. 澄清:我正在寻找当xy是浮点数时适用的答案。 Ie compare: 即比较:

double h = std::hypot(static_cast<double>(x),static_cast<double>(y));

to: 至:

double xx = static_cast<double>(x);
double yy = static_cast<double>(y);
double h = std::sqrt(xx*xx + yy*yy);

The answer is in the documentation you quoted 答案在您引用的文档中

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和y的平方和的平方根,在计算的中间阶段没有过度溢出或下溢

If x*x + y*y overflows, then if you carry out the calculation manually, you'll get the wrong answer. 如果x*x + y*y溢出,那么如果你手动执行计算,你将得到错误的答案。 If you use std::hypot , however, it guarantees that the intermediate calculations will not overflow. 但是,如果使用std::hypot ,则可以保证中间计算不会溢出。

You can see an example of this disparity here . 你可以在这里看到这种差异的一个例子。

If you are working with numbers which you know will not overflow the relevant representation for your platform, you can happily use the naive version. 如果您正在使用您知道不会溢出平台相关表示的数字,您可以愉快地使用天真版本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM