何时在`std :: sqrt(x * x + y * y)上使用`std :: hypot(x,y)` [英] When to use `std::hypot(x,y)` over `std::sqrt(x*x + y*y)`

查看:127
本文介绍了何时在`std :: sqrt(x * x + y * y)上使用`std :: hypot(x,y)`的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

std :: hypot << a href = http://en.cppreference.com/w/cpp/numeric/math/hypot>文档表示:


计算x和y平方和的平方根,中间不会出现不适当的上溢或下溢

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)

I struggle to conceive a test case where std::hypot should be used over the trivial sqrt(x*x + y*y).

以下测试表明 std :: hypot 大约比朴素的计算慢20倍。

The following test shows that std::hypot is roughly 20x slower than the naive calculation.

#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)上获得正确的结果

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

说明:我正在寻找 x时适用的答案 y 是浮点数。即比较:

Clarification: I'm looking for answers that apply when x and y are floating point numbers. I.e. compare:

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 ,则可以保证中间计算不会溢出。

If x*x + y*y overflows, then if you carry out the calculation manually, you'll get the wrong answer. If you use std::hypot, however, it guarantees that the intermediate calculations will not overflow.

您可以请参见此处

如果您使用的数字不会超出您平台的相关表示,则可以很高兴使用朴素的版本。

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.

这篇关于何时在`std :: sqrt(x * x + y * y)上使用`std :: hypot(x,y)`的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆