C++在有或不使用名称空间性std的情况下,长双精度差;
我偶然发现了我无法解释的古怪的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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在第一种情况下,您是在调用
double Round(double Code)
>来自全局名称空间的功能,该命名空间由
cmath
标题删除。在第二种情况下,您正在调用Overloaded
long double std :: round(长double)
是std
名称空间的功能,因为您使用namespace std。
前面添加
std ::
来修复代码可以通过在
回合
的您 代码>在第一种情况下,
比率 * x
被隐式转换为double
(只能存储15个有效数字),然后再将其传递给该函数。这会导致精确度的丧失,并在您的情况下产生意外的结果。没有怪癖。
In the first case you are calling
double round(double)
function from the global namespace, which is pulled in by thecmath
header.In the second case you are calling overloaded
long double std::round(long double)
function from thestd
namespace since your areusing namespace std
.You can fix your code by adding
std::
in front ofround
, as in:UPDATE:
To explain what's going on here, when you call
round
in the first case,ratio * x
is implicitly converted todouble
(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.