我想知道长双和双之间的区别 [英] I want to know the difference between a long double and a double
问题描述
对于任何算法问题,允许的误差为10 -6 .
For any algorithmic problem, an error of 10-6 is allowed.
在第一个解决方案中,我声明了long double
作为变量,并获得了WA.
I declared a long double
as a variable in my first solution and got a WA.
但是,当我将变量声明为double
时,我得到了AC.
But, when I declared a variable as double
, I got an AC.
我想知道为什么要做出此决定,因为众所周知long double
比double
更准确.除了变量,输出方法外,我什么都没改变.
I want to know why this decision was made because long double
is known to be more accurate than double
. I have not changed anything except variables, output methods.
这是我的代码:
#include <iostream>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <deque>
#include <algorithm>
using namespace std;
#define pi 3.141592653589
int main() {
double x;
double y;
double r = 0.0;
int n;
double len;
double ans = 0.0;
deque<double> dq;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> x >> y;
len = sqrt(x* x + y * y);
if (len > r) {
r = len;
dq.clear();
if ((x > 0 && y <= 0) || (x >= 0 && y < 0))
dq.push_back(360.0 + (90 + atan2(x, y) * 180 * (-1) / pi));
else
dq.push_back(90+atan2(x, y) * 180 * (-1) / pi);
} else if (r == len) {
if ((x > 0 && y <= 0) || (x >= 0 && y < 0))
dq.push_back(360 + (90 + atan2(x, y) * 180 * (-1) / pi));
else
dq.push_back(90+atan2(x, y) * 180 * (-1) / pi);
}
}
sort(dq.begin(), dq.end());
if (dq.size() >= 2) {
for (int i = 0; i < dq.size() - 1; i++) {
ans = max(ans, dq[i + 1] - dq[i]);
}
ans = max(ans, 360 - dq.back() + dq.front());
printf("%0.6f", ans);
}
else
cout << "360.000000";
}
我所做的唯一更改是:
- 将
double
更改为long double
;和 - 将
printf
格式说明符从f
更改为lf
.
- changing the
double
tolong double
; and - changing the
printf
format specifier fromf
tolf
.
推荐答案
...长双精度比双精度更精确.
... long double is known to be more accurate than double.
不,实际上不是.可能是 ,但是绝对不能保证.
No, it's really not. It may be but it's by no means guaranteed.
两种类型之间的差异在标准中进行了详细说明(在本例中为C++17 [basic.fundamental]/8
,尽管早期的迭代也具有类似的措辞).该标准对浮点类型有此规定(我强调):
The difference between the two types is detailed in the standard (in this case, C++17 [basic.fundamental]/8
, though earlier iterations also have similar wording). The standard has this to say about the floating point types (my emphasis):
共有三种浮点类型:
float
,double
和long double
.
类型double
提供的至少精度与float
一样,类型long double
提供的至少精度与double
一样.
The type double
provides at least as much precision as float
, and the type long double
provides at least as much precision as double
.
类型float
的值集是类型double
的值集的子集; double
类型的值集是long double
类型的值集的子集.
The set of values of the type float
is a subset of the set of values of the type double
; the set of values of the type double
is a subset of the set of values of the type long double
.
浮点类型的值表示形式是实现定义的.
The value representation of floating-point types is implementation-defined.
由于子集"包括两个集合完全相同的可能性(A ⊂ A
是不言自明的),因此没有实际要求long double
具有比<<更大的 范围和/或精度c1>,尽管有时确实如此.
Since "subset" includes the possibility that the two sets are identical (it's axiomatic that A ⊂ A
), there's no actual requirement than long double
has a larger range and/or precision than double
, though it sometimes does.
如果您想弄清楚实现中的区别是什么,请按照以下演示程序查看<limits>
标头中的numeric_limits
类:
If you want to figure out what the differences are in your implementation, you should be looking into the numeric_limits
class in the <limits>
header, as per the following demo program:
#include <iostream>
#include <limits>
using namespace std;
int main() {
numeric_limits<double> lim_d;
numeric_limits<long double> lim_ld;
cout << "\nmax " << lim_d.max() << " " << lim_ld.max()
<< "\nmin " << lim_d.min() << " " << lim_ld.min()
<< "\nlowest " << lim_d.lowest() << " " << lim_ld.lowest()
<< "\ndigits10 " << lim_d.digits10 << " " << lim_ld.digits10
<< '\n';
}
my 系统上的输出经过格式化,以提高可读性:
The output on my system is, formatted for readability:
double long double
============ =============
max 1.79769e+308 1.18973e+4932
min 2.22507e-308 3.3621 e-4932
lowest -1.79769e+308 -1.18973e+4932
digits10 15 18
您可以看到,对于long double
,我的范围明显更大,并且(大约)还有三位数的精度.
You can see that my range is substantially larger for a long double
and there's also (roughly) an extra three decimal digits of precision.
关于这可能会对您的代码产生什么影响,很难说,因为您实际上并未提供关于问题所在(尤其是wa
和ac
的含义)的充分描述.但是,由于long double
可能比double
具有更高的精度和/或范围,因此可以肯定的是,这可能会影响代码的行为.
In terms of what effect this can have on your code, it's difficult to say since you haven't actually provided an adequate description of what the problem is (specifically what wa
and ac
mean). However, since a long double
may have more precision and/or range than a double
, it's certainly conceivable that this may affect how your code behaves.
我还应该提到,long double
的正确格式说明符实际上是%Lf
(大写的L
)而不是%lf
.这很可能会给您带来问题,因为在注释中链接到的页面上提供了测试数据,我得到了double
/%f
和long double
/%Lf
的正确结果.
I should also mention that the correct format specifier for a long double
is actually %Lf
(capitalised L
) rather than %lf
. That may well be causing a problem for you since, with the test data given on the page you linked to in a comment, I get the correct result for double
/%f
and long double
/%Lf
.
但是它会为long double
/%lf
提供不同的结果(并为此给出gcc
警告).
But it gives different results (and a gcc
warning, for that matter) for long double
/%lf
.
这篇关于我想知道长双和双之间的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!