我想知道 long double 和 double 的区别
I want to know the difference between a long double and a double
对于任何算法题,10-6的误差是允许的。
我在我的第一个解决方案中将 long double
声明为变量并获得了 WA。
但是,当我将变量声明为 double
时,我得到了一个 AC。
我想知道为什么做出这个决定,因为众所周知 long double
比 double
更准确。除了变量,输出方法,我没有改变任何东西。
这是我的代码:
#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
。
long double
的实现在编译器和硬件上发生了变化。
Visual Studio 只是使用 long double
作为 double
的同义词。您需要在 windows 上使用英特尔编译器才能在英特尔架构或 GCC(版本 > 4.3)上使用扩展精度硬件。资料来源:https://en.wikipedia.org/wiki/Long_double
如果您想更新您的问题以包含代码示例或有关您的编译器和体系结构的详细信息,我可以在答案中添加更多详细信息。但是通常(在 Intel 上)long double 使用 80 位硬件浮点运算。
编辑:我 运行 Paxdiablo 的代码在 Sun/Oracle SparcV9 solaris 盒子上:
double long double
============ =============
max 1.79769e+308 1.18973e+4932
min 2.22507e-308 3.3621e-4932
lowest -1.79769e+308 -1.18973e+4932
digits10 15 33
... long double is known to be more accurate than double.
不,确实不是。可能,但不能保证。
标准中详细说明了这两种类型之间的区别(在本例中,C++17 [basic.fundamental]/8
,尽管早期的迭代也有类似的措辞)。该标准对浮点类型有这样的说法(我的重点):
There are three floating-point types: float
, double
, and long 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
.
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
具有 更大的 范围 and/or 精度高于 double
,尽管它有时确实如此。
如果您想弄清楚在您的实施中有什么不同 , 您应该查看 numeric_limits
class [=28] =] header,按照下面的演示程序:
#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 系统的输出格式为:
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
大得多,而且还有(大致)额外的三位小数精度。
关于这会对您的代码产生什么影响,这很难说,因为您实际上没有提供对问题所在的充分描述(特别是 wa
和 ac
意思)。但是,由于 long double
可能比 double
具有更精确的 and/or 范围,因此可以想象这可能会影响代码的行为方式。
我还应该提到 long double
的正确格式说明符实际上是 %Lf
(大写 L
)而不是 %lf
。这很可能会给您带来问题,因为根据您在评论中链接到的页面上给出的测试数据,我得到了 double
/%f
和 long double
/ 的正确结果%Lf
.
但是对于 long double
/%lf
.[=47,它给出了 不同的 结果(以及 gcc
警告,就此而言) =]
对于任何算法题,10-6的误差是允许的。
我在我的第一个解决方案中将 long double
声明为变量并获得了 WA。
但是,当我将变量声明为 double
时,我得到了一个 AC。
我想知道为什么做出这个决定,因为众所周知 long double
比 double
更准确。除了变量,输出方法,我没有改变任何东西。
这是我的代码:
#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
。
long double
的实现在编译器和硬件上发生了变化。
Visual Studio 只是使用 long double
作为 double
的同义词。您需要在 windows 上使用英特尔编译器才能在英特尔架构或 GCC(版本 > 4.3)上使用扩展精度硬件。资料来源:https://en.wikipedia.org/wiki/Long_double
如果您想更新您的问题以包含代码示例或有关您的编译器和体系结构的详细信息,我可以在答案中添加更多详细信息。但是通常(在 Intel 上)long double 使用 80 位硬件浮点运算。
编辑:我 运行 Paxdiablo 的代码在 Sun/Oracle SparcV9 solaris 盒子上:
double long double
============ =============
max 1.79769e+308 1.18973e+4932
min 2.22507e-308 3.3621e-4932
lowest -1.79769e+308 -1.18973e+4932
digits10 15 33
... long double is known to be more accurate than double.
不,确实不是。可能,但不能保证。
标准中详细说明了这两种类型之间的区别(在本例中,C++17 [basic.fundamental]/8
,尽管早期的迭代也有类似的措辞)。该标准对浮点类型有这样的说法(我的重点):
There are three floating-point types:
float
,double
, andlong double
.The type
double
provides at least as much precision asfloat
, and the typelong double
provides at least as much precision asdouble
.The set of values of the type
float
is a subset of the set of values of the typedouble
; the set of values of the typedouble
is a subset of the set of values of the typelong double
.The value representation of floating-point types is implementation-defined.
由于“子集”包括两个集合相同的可能性(A ⊂ A
是不言而喻的),因此没有实际要求比 long double
具有 更大的 范围 and/or 精度高于 double
,尽管它有时确实如此。
如果您想弄清楚在您的实施中有什么不同 , 您应该查看 numeric_limits
class [=28] =] header,按照下面的演示程序:
#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 系统的输出格式为:
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
大得多,而且还有(大致)额外的三位小数精度。
关于这会对您的代码产生什么影响,这很难说,因为您实际上没有提供对问题所在的充分描述(特别是 wa
和 ac
意思)。但是,由于 long double
可能比 double
具有更精确的 and/or 范围,因此可以想象这可能会影响代码的行为方式。
我还应该提到 long double
的正确格式说明符实际上是 %Lf
(大写 L
)而不是 %lf
。这很可能会给您带来问题,因为根据您在评论中链接到的页面上给出的测试数据,我得到了 double
/%f
和 long double
/ 的正确结果%Lf
.
但是对于 long double
/%lf
.[=47,它给出了 不同的 结果(以及 gcc
警告,就此而言) =]