c++ - 我想知道 long double 和 double 之间的区别
问题描述
对于任何算法问题,允许出现 10 -6的误差。
我在第一个解决方案中将 a 声明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 比 double 更准确。
不,真的不是。可能是,但绝不是保证。
标准中详细说明了这两种类型之间的区别(在这种情况下C++17 [basic.fundamental]/8
,虽然早期的迭代也有类似的措辞)。该标准对浮点类型有这样的说法(我的重点):
共有三种浮点类型:
float
、double
和long double
。类型至少
double
提供与一样多的精度,并且类型提供至少与 一样多的精度。float
long double
double
类型的值集是类型值
float
集的子集double
;类型的值集是类型值double
集的子集long double
。浮点类型的值表示是实现定义的。
由于“子集”包括两个集合相同的可能性(这是不言自明的A ⊂ A
),因此没有实际要求比long double
具有更大的范围和/或精度double
,尽管有时确实如此。
如果你想弄清楚你的实现有什么不同,你应该按照下面的演示程序查看标题numeric_limits
中的类:<limits>
#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';
}
为了便于阅读,我系统上的输出已格式化:
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
您可以看到我的 a 范围要大得多,long double
并且(大约)还有额外的三位小数精度。
就这会对您的代码产生什么影响而言,很难说,因为您实际上并没有充分描述问题是什么(特别是什么wa
和ac
意思)。但是,由于 along double
可能比 a 具有更高的精度和/或范围double
,因此当然可以想象这可能会影响您的代码的行为方式。
我还应该提到, a 的正确格式说明符long double
实际上是%Lf
(大写的L
)而不是%lf
. 这很可能会给您带来问题,因为根据您在评论中链接到的页面上给出的测试数据,我得到了double
/%f
和long double
/的正确结果%Lf
。
但它为/给出了不同的结果(和gcc
警告,就此而言)。long double
%lf
推荐阅读
- git - 返回上一个提交,忽略所有更改
- maven - “运行任何东西”操作不适用于 maven 命令
- java - 如何移动数组的内容?
- java - 如何对图进行不同的基本遍历?
- python - Python3 和 Selenium - 管理权限弹出窗口
- java - 从命令行使用 Json 执行 maven 项目
- typescript - 打字稿:如何使用泛型指示可以为空的属性
- python - SyntaxError:python 函数中的语法无效
- python - Advices on what kind of structure to use in Python to store music informations
- vsphere - 从所有 ESXi 主机获取硬件使用信息