Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
140 views
in Technique[技术] by (71.8m points)

c++ - I want to know the difference between a long double and a double

For any algorithmic problem, an error of 10-6 is allowed.

I declared a long double as a variable in my first solution and got a WA.

But, when I declared a variable as double, I got an AC.

I want to know why this decision was made because long double is known to be more accurate than double. I have not changed anything except variables, output methods.

Here is my code:

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

The only changes I made were:

  • changing the double to long double; and
  • changing the printf format specifier from f to lf.
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

... long double is known to be more accurate than double.

No, it's really not. It may be but it's by no means guaranteed.

The difference between the two types is detailed in the standard (in this case, C++17 [basic.fundamental]/8, though earlier iterations also have similar wording). The standard has this to say about the floating point types (my emphasis):

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.

Since "subset" includes the possibility that the two sets are identical (it's axiomatic that A ? A), there's no actual requirement than long double has a larger range and/or precision than double, though it sometimes does.

If you want to figure out what the differences are in your implementation, you should be looking into the numeric_limits class in the <limits> header, as per the following demo program:

#include <iostream>
#include <limits>
using namespace std;

int main() {
    numeric_limits<double> lim_d;
    numeric_limits<long double> lim_ld;

    cout << "
max " << lim_d.max() << " " << lim_ld.max()
         << "
min " << lim_d.min() << " " << lim_ld.min()
         << "
lowest " << lim_d.lowest() << " " << lim_ld.lowest()
         << "
digits10 " << lim_d.digits10 << " " << lim_ld.digits10
         << '
';
}

The output on my system is, formatted for readability:

              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

You can see that my range is substantially larger for a long double and there's also (roughly) an extra three decimal digits of precision.


In terms of what effect this can have on your code, it's difficult to say since you haven't actually provided an adequate description of what the problem is (specifically what wa and ac mean). However, since a long double may have more precision and/or range than a double, it's certainly conceivable that this may affect how your code behaves.

I should also mention that the correct format specifier for a long double is actually %Lf (capitalised L) rather than %lf. That may well be causing a problem for you since, with the test data given on the page you linked to in a comment, I get the correct result for double/%f and long double/%Lf.

But it gives different results (and a gcc warning, for that matter) for long double/%lf.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...