atom
atom

Reputation: 153

double & long double : are they same on my computer?

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

Answers (2)

chux
chux

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

Pascal Cuoq
Pascal Cuoq

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

Related Questions