Почему переменная типа long double генерирует абсурдный вывод, тогда как типы float и double работают нормально?

Все, что я хочу сделать в следующей программе, это напечатать произведение всех положительных чисел, меньших 30 (как в экспоненциальной, так и не экспоненциальной формах). Работает нормально, когда переменная product объявлен как float или double, но выдает абсолютно абсурдный (отрицательный) результат, когда тип long double, Поэтому, пожалуйста, ответьте на следующие два вопроса:

  1. Почему long double приводя к совершенно абсурдным (даже отрицательным) результатам float а также double типы для переменной product дает правильные результаты?

    У меня есть представление, что long double это не что иное, как "мощная" версия double, который сам по себе является "высокопроизводительной" версией float тип!!

  2. Теперь что касается типов, которые дают правильный результат для product т.е. float а также double почему они производят одинаковый вывод в экспоненциальной форме (%e) но заметно отличается вывод для неэкспоненциальной формы (%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);
}

Выход для product как плавать

The product of even numbers <30 is 4.284987e+16 
The product in non-exponential form is 42849875099910144.000000

Выход для product как двойной

The product of even numbers <30 is 4.284987e+16 
The product in non-exponential form is 42849873690624000.000000

Выход для product как долго двойной

The product of even numbers <30 is -6.078565e-192 
The product in non-exponential form is -0.000000

2 ответа

Решение

Потому что вы используете неверный спецификатор формата, чтобы распечатать его. float а также double передаются как double к printf() функция (из-за правил продвижения по умолчанию, применяемых к нему, так как она варьируется), но long double передается как long doubleи вы должны использовать %Lf спецификатор преобразования для него, иначе ваша программа вызывает неопределенное поведение.

Что касается второго вопроса: float имеет только 23 бита мантиссы и может содержать только около 7 цифр точности, остальное - просто "мусор".

                  float error
precision: 1234567↓90ABCDEF digits
float:     42849875099910144.000000
double:    42849873690624000.000000

Как видите, разница в 8-м символе. Двойной может быть с точностью до 16 символов, очевидно, это будет более точным

Другие вопросы по тегам