Почему переменная типа long double генерирует абсурдный вывод, тогда как типы float и double работают нормально?
Все, что я хочу сделать в следующей программе, это напечатать произведение всех положительных чисел, меньших 30 (как в экспоненциальной, так и не экспоненциальной формах). Работает нормально, когда переменная product
объявлен как float
или double
, но выдает абсолютно абсурдный (отрицательный) результат, когда тип long double
, Поэтому, пожалуйста, ответьте на следующие два вопроса:
Почему
long double
приводя к совершенно абсурдным (даже отрицательным) результатамfloat
а такжеdouble
типы для переменнойproduct
дает правильные результаты?У меня есть представление, что
long double
это не что иное, как "мощная" версияdouble
, который сам по себе является "высокопроизводительной" версиейfloat
тип!!- Теперь что касается типов, которые дают правильный результат для
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 символов, очевидно, это будет более точным