【问题标题】:I want to know the difference between a long double and a double我想知道 long double 和 double 之间的区别
【发布时间】:2018-11-01 04:36:58
【问题描述】:

对于任何算法问题,允许出现 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";
}

我所做的唯一更改是:

  • double更改为long double;和
  • printf 格式说明符从 f 更改为 lf

【问题讨论】:

  • 你能解释一下WAAC是什么吗?

标签: c++ variables double long-integer


【解决方案1】:

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

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

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

共有三种浮点类型:floatdoublelong double

double 类型提供的精度至少float 一样高,long double 类型提供的精度至少double 一样高。

float 类型的值集是double 类型的值集的子集; double 类型的值集是 long double 类型的值集的子集。

浮点类型的值表示是实现定义的。

由于“子集”包括两个集合相同的可能性(A ⊂ A 是不言而喻的),因此没有实际要求比 long double 具有比 @ 更大的范围和/或精度987654336@,虽然有时会。

如果您想弄清楚在您的实现中有什么不同,您应该按照以下演示程序查看&lt;limits&gt; 标头中的numeric_limits 类: p>

#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 具有更高的精度和/或范围,因此当然可以想象这可能会影响代码的行为方式。

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

但它为long double/%lf 提供了不同的结果(以及gcc 警告)。

【讨论】:

  • 只是关于演示的一点点:一般来说,最好为标准的一部分引用 标签 而不是部分编号和标题。标签不会因版本而异。所以“[basic.fundamental]/8”而不是“6.9.1 基本类型/8”。我手边没有 C++17,但在 C++14 中,[basic.fundamental] 是 3.9.1。
  • 我会接受的,@Peter,这是个好建议。更改我以前的所有答案需要相当 很多努力:-) 但如果他们需要更新,我会这样做,以及所有未来的答案。跨度>
  • 感谢您的回答。正如你所说,如果我在使用双精度时没有出错,那么在使用长双精度时我不应该得到任何错误。但是,double 没有错误,long double 也有错误。我认为这会发生,因为我做了各种算术运算。所以想知道double和long double的变量操作是否有区别。
  • @진민수,那么您将需要提供更多详细信息,特别是显示问题的代码。在那之前,我们只能建议/猜测。就您在先前评论中的具体问题而言:是的,有区别。不一定以方式的方式完成事情,但肯定是可能扩展了long double类型的范围和精度。
  • 简单解释问题,如果我在坐标平面上输入一个点,我找到到原点的最长距离,发现这些点是从原点开始的直线。当我从这些直线中选择两条直线时,我找到了角度最大的两条直线的角度。来源:acmicpc.net/problem/16115
【解决方案2】:

long double 的实现在编译器和硬件上发生了变化。

Visual Studio 只使用long double 作为double 的同义词。您将需要在 Windows 上使用英特尔编译器,以利用英特尔架构或 GCC(版本 > 4.3)上的扩展精度硬件。来源:https://en.wikipedia.org/wiki/Long_double

如果您想更新您的问题以包含有关您的编译器和架构的代码示例或详细信息,我可以在答案中添加更多详细信息。但是一般(在 Intel 上)long double 使用 80 位硬件浮点运算。

编辑:我在 Sun/Oracle SparcV9 solaris 机器上运行 Paxdiablo 的代码:

              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 不是double 的同义词。它必须是一个独特的类型。它可以是相同的大小并具有相同的属性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-26
  • 1970-01-01
  • 2021-11-07
  • 1970-01-01
相关资源
最近更新 更多