C++在有或不使用名称空间性std的情况下,长双精度差;

发布于 2025-02-06 11:54:57 字数 1432 浏览 1 评论 0原文

我偶然发现了我无法解释的古怪的C ++行为。

我试图在调整图像(保持比率)时计算图像的尺寸,以拟合尽可能多的屏幕。 x,y变量是图像的维度,x,y变量是屏幕的维度。当最终的维度不是整数时,我需要使用标准数学规则将它们弄圆。

该输入的程序49999999999999999 10 1000000000000000000 19给出(不正确的)答案950000000000000000 19

#include <iostream>
#include <cmath>
#include <algorithm>

int main()
{
    long long x, y, X, Y;
    std::cin >> x >> y >> X >> Y;

    long double ratio = std::min((long double)X/x, (long double)Y/y);

    x = round(ratio*x);
    y = round(ratio*y);

    std::cout << x << " " << y << std::endl;
    return 0;
}

但是,下面的代码(只有更改是使用命名空间std;和删除std ::来自main函数函数主体)给出了94999999999999998 19 。

#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;

int main()
{
    long long x, y, X, Y;
    cin >> x >> y >> X >> Y;

    long double ratio = min((long double)X/x, (long double)Y/y);

    x = round(ratio*x);
    y = round(ratio*y);

    cout << x << " " << y << endl;
    return 0;
}

我正在使用g ++(ubuntu 9.4.0-1ubuntu1〜20.04.1)9.4.0并用g ++ -Std = C ++ 17 -wall -wall -wextra -wshadow -wshadow 。

I have stumbled upon quirky C++ behavior that I cannot explain.

I am trying to calculate the dimensions of an image when resizing it (maintaining its ratio) to fit as much screen as possible. The x, y variables are dimensions of the image and X, Y variables are dimensions of the screen. When the resulting dimensions are not integers, I need to round them using standard rules of mathematics.

This program for inputs 499999999999999999 10 1000000000000000000 19 gives the (incorrect) answer of 950000000000000000 19.

#include <iostream>
#include <cmath>
#include <algorithm>

int main()
{
    long long x, y, X, Y;
    std::cin >> x >> y >> X >> Y;

    long double ratio = std::min((long double)X/x, (long double)Y/y);

    x = round(ratio*x);
    y = round(ratio*y);

    std::cout << x << " " << y << std::endl;
    return 0;
}

However, code below (only change is using namespace std; and removing std:: from main function body) gives the correct answer of 949999999999999998 19.

#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;

int main()
{
    long long x, y, X, Y;
    cin >> x >> y >> X >> Y;

    long double ratio = min((long double)X/x, (long double)Y/y);

    x = round(ratio*x);
    y = round(ratio*y);

    cout << x << " " << y << endl;
    return 0;
}

I am using g++ (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0 and compiling the program with g++ -std=c++17 -Wall -Wextra -Wshadow.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

别念他 2025-02-13 11:54:57

在第一种情况下,您是在调用 double Round(double Code)>来自全局名称空间的功能,该命名空间由cmath标题删除。

在第二种情况下,您正在调用Overloaded long double std :: round(长double)std名称空间的功能,因为您使用namespace std

前面添加std ::来修复代码

#include <iostream>
#include <cmath>
#include <algorithm>

int main()
{
    long long x, y, X, Y;
    std::cin >> x >> y >> X >> Y;

    auto ratio = std::min((long double)X / x, (long double)Y / y);

    x = std::round(ratio * x); // <-- add std:: here
    y = std::round(ratio * y); // <-- add std:: here

    std::cout << x << " " << y;
    return 0;
}

可以通过在回合

您 代码>在第一种情况下,比率 * x被隐式转换为double(只能存储15个有效数字),然后再将其传递给该函数。

这会导致精确度的丧失,并在您的情况下产生意外的结果。没有怪癖。

In the first case you are calling double round(double) function from the global namespace, which is pulled in by the cmath header.

In the second case you are calling overloaded long double std::round(long double) function from the std namespace since your are using namespace std.

You can fix your code by adding std:: in front of round, as in:

#include <iostream>
#include <cmath>
#include <algorithm>

int main()
{
    long long x, y, X, Y;
    std::cin >> x >> y >> X >> Y;

    auto ratio = std::min((long double)X / x, (long double)Y / y);

    x = std::round(ratio * x); // <-- add std:: here
    y = std::round(ratio * y); // <-- add std:: here

    std::cout << x << " " << y;
    return 0;
}

UPDATE:

To explain what's going on here, when you call round in the first case, ratio * x is implicitly converted to double (which can only store 15 significant digits) before it is passed to the function.

This leads to loss of precision and an unexpected result in your case. No quirks.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文