c – 什么时候在`std :: sqrt(x * x y * y)’上使用`std :: hypot(x,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是浮点数时,我正在寻找适用的答案.即比较:

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.

如果您正在使用的数字,您知道不会溢出您的平台相关的代表,您可以高兴地使用天真的版本.

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...