首页 > 解决方案 > 我想知道 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";
}

我所做的唯一更改是:

标签: c++variablesdoublelong-integer

解决方案


...众所周知,long double 比 double 更准确。

不,真的不是。可能是,但绝不是保证。

标准中详细说明了这两种类型之间的区别(在这种情况下C++17 [basic.fundamental]/8,虽然早期的迭代也有类似的措辞)。该标准对浮点类型有这样的说法(我的重点):

共有三种浮点类型:floatdoublelong double

类型至少double提供与一样多的精度,并且类型提供至少与 一样多的精度。floatlong doubledouble

类型的值集是类型值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并且(大约)还有额外的三位小数精度。


就这会对您的代码产生什么影响而言,很难说,因为您实际上并没有充分描述问题是什么(特别是什么waac意思)。但是,由于 along double可能比 a 具有更高的精度和/或范围double,因此当然可以想象这可能会影响您的代码的行为方式。

我还应该提到, a 的正确格式说明符long double实际上是%Lf(大写的L)而不是%lf. 这很可能会给您带来问题,因为根据您在评论中链接到的页面上给出的测试数据,我得到了double/%flong double/的正确结果%Lf

但它为/给出了不同的结果(和gcc警告,就此而言)。long double%lf


推荐阅读