Because you're using the wrong format specifier to print it out. float
and double
are passed as double
to the printf()
function (due to default promotion rules applying to it since it's variadic), but long double
is passed as long double
, and you have to use the %Lf
conversion specifier for it, else your program invokes undefined behavior.
Why is "long double" type of a variable producing absurd output while "float" and "double" type works fine?
-
13-04-2022 - |
Вопрос
All I want the following program to do is to print the product of all positive numbers less than 30 (in both exponential and non-exponential forms). It works fine when the variable product
is declared as a float
or a double
,but produces totally absurd (negative) result when the type is long double
. So please answer these two questions arising from it:
Why is
long double
producing totally absurd (even negative) results whilefloat
anddouble
types for the variableproduct
producing correct results?I have this notion that
long double
is nothing but a "high-capacity" version ofdouble
, which is itself a "high-capacity" version offloat
type !!Now as of the types that are producing the correct result for
product
, iefloat
anddouble
, why do they produce the same output in exponential form (%e
) but noticeably different output for non-exponential form (%f
) ?
#include<stdio.h>
int main(void)
{
int j;
float product=1; //Works fine
//double product=1; //Works fine
//long double product=1; //Produces absurd output.
for(j=2;j<=30;j=j+2)
product=product*j;
printf("The product of even numbers <30 is %e \n",product);
printf("The product in non-exponential form is %f",product);
}
Output for product
as float
The product of even numbers <30 is 4.284987e+16
The product in non-exponential form is 42849875099910144.000000
Output for product
as double
The product of even numbers <30 is 4.284987e+16
The product in non-exponential form is 42849873690624000.000000
Output for product
as long double
The product of even numbers <30 is -6.078565e-192
The product in non-exponential form is -0.000000
Решение
Другие советы
For the second question: float
has only 24 bits of significand and can only hold about ~6-7 digits of precision (the real precision is not an integer because floating-point types in computer generally use binary whereas us humans use decimal), the rest is just "garbage".
float error
precision: 1234567↓90ABCDEF digits
float: 42849875099910144.000000
double: 42849873690624000.000000
As you see, the difference is at the 8th digit. double
has 53 bits of significand and could be accurate to about ~15 decimal digits which obviously means it would be more precise. But if rounded to the 6th digit (which is the default for %e) then both results in 4.284987e+16 which leads to the misconception that the result in float
and double
are the same even though they're not. If you print more decimal digits with %.20e
for example, then you'll see the same difference as %f
If you fix the format specifier of long double
and do more iterations then double
will suffer the same issue if long double
is more precise. For example if you increase the limit in your code from 30 to 50 then you'll get this
float: 5.204699e+32
520469877396214593413323729928192.000000
double: 5.204698e+32
520469842636666625085618390040576.000000
long double: 5.204698e+32
520469842636666622693081088000000.000000