我想知道 long double 和 double 的区别

I want to know the difference between a long double and a double

对于任何算法题,10-6的误差是允许的。

我在我的第一个解决方案中将 long double 声明为变量并获得了 WA。

但是,当我将变量声明为 double 时,我得到了一个 AC。

我想知道为什么做出这个决定,因为众所周知 long doubledouble 更准确。除了变量,输出方法,我没有改变任何东西。

这是我的代码:

#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";
}

我所做的唯一更改是:

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 大得多,而且还有(大致)额外的三位小数精度。


关于这会对您的代码产生什么影响,这很难说,因为您实际上没有提供对问题所在的充分描述(特别是 waac意思)。但是,由于 long double 可能比 double 具有更精确的 and/or 范围,因此可以想象这可能会影响代码的行为方式。

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

但是对于 long double/%lf.[=47,它给出了 不同的 结果(以及 gcc 警告,就此而言) =]