Как бы я напечатал максимально возможный float и double в C?
Для следующего кода,
#include <stdio.h>
#include <limits.h>
#include <float.h>
int main(void) {
printf("double max = %??n", DBL_MAX);
printf("double min = %??n", DBL_MIN);
printf("double epsilon = %??n", DBL_EPSILON);
printf("float epsilon = %??n", FLT_EPSILON);
printf("float max = %??n", FLT_MAX);
printf("float min = %??nn", FLT_MIN);
return 0;
}
Какие спецификаторы я должен был бы использовать вместо ??это для того, чтобы printf отображал различные количества в виде десятичных чисел соответствующего размера?
3 ответа:
Используйте тот же формат, что и для любых других значений этих типов:
#include <float.h> #include <stdio.h> int main(void) { printf("FLT_MAX = %g\n", FLT_MAX); printf("DBL_MAX = %g\n", DBL_MAX); printf("LDBL_MAX = %Lg\n", LDBL_MAX); }
Аргументы типа
float
повышаются доdouble
для вариадических функций, таких какprintf
, поэтому вы используете один и тот же формат для обоих.
%f
выводит значение с плавающей запятой, используя десятичную систему счисления без экспоненты, что даст вам очень длинную строку (в основном незначительных) цифр для очень больших значений.
%e
заставляет использовать показатель степени.
%g
использует либо%f
, либо%e
, в зависимости от величины печатаемого числа.В моей системе вышеописанное выводит следующее:
FLT_MAX = 3.40282e+38 DBL_MAX = 1.79769e+308 LDBL_MAX = 1.18973e+4932
Как указывает Эрик Постпишил в комментарии, выше печатаются только приближенные значения. Вы можете напечатать больше цифр, указав точность (количество цифр, которое вам понадобится, зависит от точности типов); например, вы можете заменить
%g
на%.20g
.Или, если ваша реализация поддерживает его, C99 добавил возможность печати значения с плавающей запятой в шестнадцатеричном формате с необходимой точностью:
Но результат не так легко читается человеком, как обычный десятичный формат:printf("FLT_MAX = %a\n", FLT_MAX); printf("DBL_MAX = %a\n", DBL_MAX); printf("LDBL_MAX = %La\n", LDBL_MAX);
FLT_MAX = 0x1.fffffep+127 DBL_MAX = 0x1.fffffffffffffp+1023 LDBL_MAX = 0xf.fffffffffffffffp+16380
(Примечание:
main()
- устаревшее определение; вместо этого используйтеint main(void)
.)
Чтобы вывести аппроксимации максимумов с достаточным количеством цифр для представления фактических значений (результатом преобразования напечатанного значения обратно в значение с плавающей запятой должно быть исходное значение), можно использовать:
#include <float.h> #include <stdio.h> int main(void) { printf("%.*g\n", DECIMAL_DIG, FLT_MAX); printf("%.*g\n", DECIMAL_DIG, DBL_MAX); printf("%.*Lg\n", DECIMAL_DIG, LDBL_MAX); return 0; }
В C 2011 Вы можете использовать более конкретный
FLT_DECIMAL_DIG
,DBL_DECIMAL_DIG
, иLDBL_DECIMAL_DIG
вместоDECIMAL_DIG
.Чтобы вывести точные значения, вместо аппроксимаций, нужно указать большую точность.
(int) (log10(x)+1)
цифр должно быть достаточно.Аппроксимации минимумов и эпсилоны могут быть напечатаны с достаточной точностью таким же образом. Однако вычисление количества цифр, необходимых для точных значений, может оказаться более сложным, чем для максимумов. (Технически это может быть невозможно в экзотических реализациях C. Например, система с плавающей запятой с основанием три будет иметь минимум, не представимый в любом конечном числе десятичных разрядов. Я не знаю о каких-либо таких реализациях в использовании.)
Вы можете использовать последние три отпечатка в моем решении к упражнению 2.1 из языка программирования C
// float or IEEE754 binary32 printf( "float: {min: %e, max: %e}, comp: {min: %e, max: %e}\n", FLT_MIN, FLT_MAX, pow(2,-126), pow(2,127) * (2 - pow(2,-23)) ); // double or IEEE754 binary64 printf( "double: {min: %e, max: %e}, comp: {min: %e, max: %e}\n", DBL_MIN, DBL_MAX, pow(2,-1022), pow(2,1023) * (2 - pow(2,-52)) ); // long double or IEEE754 binary 128 printf( "long double: {min: %Le, max: %Le}, comp: {min: %Le, max: %Le}\n", LDBL_MIN, LDBL_MAX, powl(2,-16382), powl(2,16383) * (2 - powl(2,-112)) );
Очевидно, что максимальные значения вычисляются в соответствии с IEEE 754. Полное решение доступно по ссылке: https://github.com/mat90x/tcpl/blob/master/types_ranges.c