0

Although there are some answers are on this websites, I still can't figure out the meaning of sizeof(long double). Why is the output of printing var3 is 3.141592653589793115998?

When I try to execute codes from another person, it runs different from another person. Could somebody help me to solve this problem?

My testing codes:

float var1 =3.1415926535897932;
double var2=3.1415926535897932;
long double var3 =3.141592653589793213456;


printf("%d\n",sizeof(float));


printf("%d\n",sizeof(double));

printf("%d\n",sizeof(long double));

printf("%.16f\n",var1);
printf("%.16f\n",var2);
printf("%.21Lf\n",var3);

output of my testing codes:

4
8
16
3.1415927410125732
3.1415926535897931
3.141592653589793115998

Codes are the same with another person, but the output from another person is:

4
8
12
3.1415927410125732
3.1415926535897931
3.141592741012573213359

Could somebody tell me why the output of us are different?

phuclv
  • 37,963
  • 15
  • 156
  • 475
Matt Matt
  • 11
  • 1
  • 3
    Welcome to SO. Please add your code to the question. Don't force the readers to follow external links. Also please do not post text as pictures. Include is as text instead. – Gerhardh Jun 24 '20 at 10:33
  • 4
    With the GNU C Compiler, long double is 80-bit extended precision on x86 processors regardless of the physical storage used for the type (which can be either 96 or 128 bits),[10] On some other architectures, long double can be double-double (e.g. on PowerPC[11][12][13]) or 128-bit quadruple precision (e.g. on SPARC[14]). As of gcc 4.3, a quadruple precision is also supported on x86, but as the nonstandard type __float128 rather than long double.[15] [[More info](https://en.wikipedia.org/wiki/Long_double)] – David Ranieri Jun 24 '20 at 10:34
  • Please look at all the images which are 'this is my testing codes', ' this is the output of my testing codes' and 'this is the codes and output from another person' if you are gonna help. Thank you! – Matt Matt Jun 24 '20 at 10:36
  • @DavidRanieri So, can you tell me what can I do if I want the output of sizeof(long double) is 10 bytes? Is that I should not use the GNU C Compiler? Or something that you can suggest to me? Thank you! – Matt Matt Jun 24 '20 at 10:46
  • 1
    _Is that I should not use the GNU C Compiler?_ What is your problem? Do you need more precision than the provided by some implementation? We often work with epsilons to deal with those kind of issues (`LDBL_EPSILON` in `float.h`), take a look to https://en.wikipedia.org/wiki/Machine_epsilon – David Ranieri Jun 24 '20 at 10:57
  • (a) The output is different because you and the other person executed the program in different C implementations, and the C standard does not require C implementations to behave identically. They may vary in the sizes and formats used for `long double` and other types and in the quality of conversions between floating-point and decimal (as in `printf`). That said, it does look like the other’s implementation may be low quality in its `long double` formatting or format. (b) Your question “Why is the output of printing var3 is 3.141592653589793115998?” is unclear. That is the output because… – Eric Postpischil Jun 24 '20 at 11:22
  • … that is the result one gets from rounding the `long double` value to 21 decimal digits after the decimal point. What else would you expect? Are you unclear on how the source text `3.141592653589793213456` was converted to `long double`, which involves rounding (adjusting) to fit in the `long double` format? (c) When printing the result of `sizeof`, use `%zu`, not `%d`. `%zu` is for formatting `size_t` types, which `sizeof` produces. `%d` is for `int`. (d) FYI, 3.141592653589793213456 is off from the correct value of π, which is closer to 3.1415926535897932384626433. – Eric Postpischil Jun 24 '20 at 11:24

2 Answers2

0

Floating point numbers -inside our computers- are not mathematical real numbers.

They have lots of counter-intuitive properties (e.g. (1.0-x) + x in your C code can be different of 1....). For more, read the floating-point-gui.de

Be also aware that a number is not its representation in digits. For example, most of your examples are approximations of the number π (which, intuitively speaking, has an infinite number of digits or bits, since it is a trancendental number, as proven by Évariste Galois and Niels Abel). The continuum hypothesis is related.

I still can't figure out the meaning of sizeof(long double).

It is the implementation specific ratio of the number of bytes (or octets) in a long double automatic variable vs the number of bytes in a char automatic variable.

The C11 standard (read n1570 and see this reference) does allow an implementation to have sizeof(long double) being, like sizeof(char), equal to 1. I cannot name such an implementation, but it might be (theoretically) the case on some weird computer architectures (e.g. some DSP).

Could somebody tell me why the output of us are different?

What make you think they could be equal?

Practically speaking, floating point numbers are often IEEE754. But on IBM mainframes (e.g. z/Series) or on VAXes they are not.

float var1 =3.1415926535897932;
double var2 =3.1415926535897932;

Be aware that it could be possible to have a C implementation where (double)var1 != var2 or where var1 != (float)var2 after executing these above instructions.

If you need more precision that what long double achieve on your particular C implementation (e.g. your recent GCC compiler, which could be a cross-compiler), consider using some arbitrary precision arithmetic library such as GMPlib.

I recommend carefully reading the documentation of printf(3), and of every other function that you are using from your C standard library. I also suggest to read the documentation of your C compiler.

You might be interested by static program analysis tools such as Frama-C or the Clang static analyzer. Read also this draft report.

If your C compiler is a recent GCC, compile with all warnings and debug info, so gcc -Wall -Wextra -g and learn how to use the GDB debugger.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
0

Could somebody tell me why the output of us are different?

C allows different compilers/implementations to use different floating point encoding and handle evaluations in slightly different ways.

Precision

The difference in sizeof hint that the 2 implementations may employ different precision. Yet the difference could be due to padding, In this case, extra bytes added to preserve an alignment for performance reasons.

A better precision assessment is to print epsilon: the difference between 1.0 and the next larger value of the type.

#include <float.h>

printf("%e %e %Le\n", FLT_EPSILON, DBL_EPSILON, LDBL_EPSILON);

Sample result

1.192093e-07 2.220446e-16 1.084202e-19

FLT_EVAL_METHOD

When this is 0, floating point types evaluate to that type. With other values like 2, floating point evaluate using wider types and only in the end save the result to the target type.

printf("FLT_EVAL_METHOD %d\n", FLT_EVAL_METHOD);

Two of several possible values indicated below:

FLT_EVAL_METHOD
0 evaluate all operations and constants just to the range and precision of the type;
2 evaluate all operations and constants to the range and precision of the long double type.

Notice the constants 3.1415926535897932, 3.141592653589793213456 are both normally double constants. Neither has an L suffix that would make the long double. Both have the same double value of 3.1415926535897931... and val2, val3 should get the same value. Yet with FLT_EVAL_METHOD==2, constants can evaluated as a long double and that is certainly what happened in "the output from another person" code.

Print FLT_EVAL_METHOD to see that difference.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256