Question

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:

  1. Why is long double producing totally absurd (even negative) results while float and double types for the variable product producing correct results?

    I have this notion that long double is nothing but a "high-capacity" version of double, which is itself a "high-capacity" version of float type !!

  2. Now as of the types that are producing the correct result for product, ie float and double, 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
Was it helpful?

Solution

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.

OTHER TIPS

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

https://ideone.com/L6P9d6

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top