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
.
... 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 << "\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';
}
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
.
The implementation of long double
changes on the compiler and the hardware.
Visual Studio just uses long double
as a synonym for double
. You will need to use the intel compiler on windows to make use of extended precision hardware on intel architectures, or GCC (versions > 4.3). Source: https://en.wikipedia.org/wiki/Long_double
If you want to update your question to include a code sample or details on your compiler & architecture, I can add possibly more detail to the answer. But generally (on Intel) long double uses 80-bit hardware floating point operations.
EDIT: I ran Paxdiablo's code on a Sun/Oracle SparcV9 solaris box:
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
By using this code you can easily understand that the long double should be twice as precise as the double.
#include<iostream>
using namespace std;
main()
{
cout<<"size of double is "<<sizeof(double)<<" bytes"<<endl;
cout<<"size of long double is "<<sizeof(long double)<<" bytes";
return 0;
}