Reputation: 153
This is ANSI C code:
float x = 3.14159264351134890172;
double y = 3.14159264351134890172;
long double z = 3.14159264351134890172;
printf("%f\n",x);
printf("%f\n",y);
printf("%f\n",z);
printf("%.20f\n",x);
printf("%.20f\n",y);
printf("%.20f\n",z);
Output of this code is:
3.141593
3.141593
3.141593
3.14159274101257324219
3.14159264351134881466
3.14159264351134881466
See last output line. I have read that long double
gives accuracy of 19 digits after decimal points. But here I get 15 digits accuracy after decimal point. So there is no difference between double
and long double
in my computer. I am using linux kernel 2.6.32-358.el6.x86_64
with CentOS.
My C compiler is gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC)
Why is this so ? If it depends on computer hardware/architecture, how do I purchase my linux machine in which long double is more precise than double ? Does it depend on my C compiler also ? If yes, how do I choose my C compiler ?
For float
value range is 1.2E-38 to 3.4E+38
. I do not understand this. From above example we see we can not store correctly a fractional decimal number such as 3.1415926 in a float
variable. My machine will store correctly only 3.141592 in that float
variable. So I have lost last 7th digit which is 6 here. Then why do we say float
range is 1.2*10^-38 ?
Isn't it that We can not store upto 10^-38 but we can store upto 10^-6 for a float
variable in C ?
Upvotes: 1
Views: 769
Reputation: 153338
Values exist to help answer OP's investigation and can be directly printed to discern how alike double
and long double
. They could be exactly the same.
To find the precision of various floating point type, print ***_MANT_DIG
number of base-
FLT_RADIX
digits in the floating-point significand,p
C11§5.2.4.2.2 11
#include <float.h>
printf("FLT_RADIX %d\n", FLT_RADIX); // Almost always 2
printf("DBL_MANT_DIG %d\n", DBL_MANT_DIG);
printf("LDBL_MANT_DIG %d\n", LDBL_MANT_DIG);
To find how many decimal digits to print that matches the FP exact value, use ***_DIG
(Round trips "text-FP-text" as expected)
printf("DBL_DIG %d\n", DBL_DIG);
printf("LDBL_DIG %d\n", LDBL_DIG);
To find how many decimal digits to print that the FP exact value maybe effected, use ***_DECIMAL_DIG
(Round trips "FP-text-FP" as expected)
printf("DBL_DECIMAL_DIG %d\n", DBL_DECIMAL_DIG);
printf("LDBL_DECIMAL_DIG %d\n", LDBL_DECIMAL_DIG);
double d = 3;
long double ld = 3;
printf("(double) 1/3 %.*e %.*e\n", DBL_DIG - 1, 1 / d,
DBL_DECIMAL_DIG - 1, 1 / d);
printf("(long double) 1/3 %.*Le %.*Le\n", LDBL_DIG - 1, 1 / ld,
LDBL_DECIMAL_DIG - 1, 1 / ld);
Example output
FLT_RADIX 2
DBL_MANT_DIG 53
LDBL_MANT_DIG 64
DBL_DIG 15
LDBL_DIG 18
DBL_DECIMAL_DIG 17
LDBL_DECIMAL_DIG 21
(double) 1/3 3.33333333333333e-01 3.3333333333333331e-01
(long double) 1/3 3.33333333333333333e-01 3.33333333333333333342e-01
Notes:
For range issues, print ***_MAX, ***_MIN
.
Be sure to use an L
in the print specifier for long double
.
Upvotes: 1
Reputation: 80255
First, you should print long double
values with %Lf
.
Second, if you want your long double
variable to contain a value that cannot be represented as a double
, you should not initialize it with a double
constant. 3.14159264351134890172
has type double
and if your compiler defines FLT_EVAL_METHOD
to 0 or 1, using long double z = 3.14159264351134890172;
sets z
to a double
value even if the type long double
could represent that constant more closely on your platform. Instead, the line should read:
long double z = 3.14159264351134890172L;
The short answer to your questions after “For float value range is 1.2E-38 to 3.4E+38 …” is that floating-point formats on your machine are in base 2, and that the representable values are not the same in these formats as if they were represented in base 10. The type float
on your platform provides exactly 24 binary digits of precision. The type double
provides 53, and you should be able to expect long double
to provide 64. The long answer is too long for the StackOverflow format, but you might start by reading http://floating-point-gui.de .
Upvotes: 5