Difference between long double and double in C and C++
To quote the C++ standard, §3.9.1 ¶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. Integral and floating types are collectively called arithmetic types. Specializations of the standard template std::numeric_limits (18.3) shall specify the maximum and minimum values of each arithmetic type for an implementation.
That is to say that double
takes at least as much memory for its representation as float
and long double
at least as much as double
. That extra memory is used for more precise representation of a number.
On x86 systems, float
is typically 4 bytes long and can store numbers as large as about 3×10³⁸ and about as small as 1.4×10⁻⁴⁵. It is an IEEE 754 single-precision number that stores about 7 decimal digits of a fractional number.
Also on x86 systems, double
is 8 bytes long and can store numbers in the IEEE 754 double-precision format, which has a much larger range and stores numbers with more precision, about 15 decimal digits. On some other platforms, double
may not be 8 bytes long and may indeed be the same as a single-precision float
.
The standard only requires that long double
is at least as precise as double
, so some compilers will simply treat long double
as if it is the same as double
. But, on most x86 chips, the 10-byte extended precision format 80-bit number is available through the CPU's floating-point unit, which provides even more precision than 64-bit double
, with about 21 decimal digits of precision.
Some compilers instead support a 16-byte (128-bit) IEEE 754 quadruple precision number format with yet more precise representations and a larger range.
long double vs double
Quoting from Wikipedia:
On the x86 architecture, most compilers implement long double as the 80-bit extended precision type supported by that hardware (sometimes stored as 12 or 16 bytes to maintain data structure .
and
Compilers may also use long double for a 128-bit quadruple precision format, which is currently implemented in software.
In other words, yes, a long double
may be able to store a larger range of values than a double
. But it's completely up to the compiler.
Long Double vs Long Long
long long
is integer (possibly with more range than long
)long double
is floating point (possibly with more range/precision than double
)long float
does not exist.
The integer types sorted by range are
_Bool
char
orsigned char
orunsigned char
short
(orshort int
) orshort unsigned
int
orunsigned
long
(orlong int
) orlong unsigned
long long
(orlong long int
) orlong long unsigned
The floating-point types sorted by range/precision are
float
double
long double
What is the difference between double and long double data type in c language
What is the major difference between double and long double data type in c?
Quoting from N1570 section "6.2.5 Types" this is what the C standard says:
There are three real floating types, designated as float, double, and long
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
This means that long double
is a floating point type having at least the same precision as the floating point type double
.
So maybe long double
is the same as double
. Maybe it has better precision than double
. The C standard only tells us that long double
can't have worse precision than double
.
This is further expanded in Annex E of the standard where the "minimum requirements" for double and long double is the same.
So the difference - if any - depends on your system.
Also notice that <float.h> on your system gives you information about the three floating point types on your system. For that please refer to the "5.2.4.2.2 Characteristics of floating types <float.h>" of the standard - it's too much info to be pasted into this answer.
BTW:
Instead of using pointer values you could have printed the size, like:
printf("size of double %zu\n", sizeof(double));
printf("size of long double %zu\n", sizeof(long double));
If the sizes are different then it is very likely that long double
has better precision than double
.
I want to know the difference between a long double and a double
... 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
, andlong double
.The type
double
provides at least as much precision asfloat
, and the typelong double
provides at least as much precision asdouble
.The set of values of the type
float
is a subset of the set of values of the typedouble
; the set of values of the typedouble
is a subset of the set of values of the typelong 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
.
Does double have a greater range than long?
The number of possible doubles, and the number of possible longs is the same, they are just distributed differently*.
The longs are uniformly distributed, while the floats are not. You can Read more here.
I'd write more, but for some reason the cursor is jumping around all over the place on my phone.
Edit: This might actually be more helpful: http://en.wikipedia.org/wiki/Double-precision_floating-point_format#section_1
Edit2: and this is even better: http://blogs.msdn.com/b/dwayneneed/archive/2010/05/07/fun-with-floating-point.aspx
* According to that link, it would seem that there are actually more longs, since some doubles are lost due to the way NaNs and other special numbers are represented.
what is the exact range of long double in c++?
Why not ask your compiler? std::numeric_limits<long double>
is defined.
long double smallest = std::numeric_limits<long double>::min();
long double largest = std::numeric_limits<long double>::max();
long double lowest = std::numeric_limits<long double>::lowest();
std::cout << "lowest " << lowest << std::endl;
std::cout << "largest " << largest << std::endl;
std::cout << "smallest " << smallest << std::endl;
Running this code on godbolt.org with x86-64 GCC 11.2 gives me:
lowest -1.18973e+4932
largest 1.18973e+4932
smallest 3.3621e-4932
It might vary for your platform, of course.
Related Topics
How to Emulate Template≪Auto X≫
Overload Resolution Failure When Streaming Object Via Implicit Conversion to String
String Literal Address Across Translation Units
Why Is Out-Of-Bounds Pointer Arithmetic Undefined Behaviour
Are Variable Length Arrays There in C++
Can Standard Container Templates Be Instantiated With Incomplete Types
What Is the Logic Behind the "Using" Keyword in C++
Why Should Exceptions Be Used Conservatively
Difference Between Static, Auto, Global and Local Variable in the Context of C and C++
How to Properly Use Widechartomultibyte
Interacting With C++ Classes from Swift
Difference Between Undefined Behavior and Ill-Formed, No Diagnostic Message Required
Why Does Printf() Promote a Float to a Double
Getting Started With Opencv 2.4 and Mingw on Windows 7