Диапазоны типа данных с плавающей точкой в C?

Я читаю книгу на языке C, говоря о диапазонах с плавающей запятой, автор дал таблицу:

<code>Type     Smallest Positive Value  Largest value      Precision
====     =======================  =============      =========
float    1.17549 x 10^-38         3.40282 x 10^38    6 digits
double   2.22507 x 10^-308        1.79769 x 10^308   15 digits
</code>

Я не знаю, откуда взялись числа в столбцах «Наименьшее положительное» и «Наибольшее значение».

 Jerry Coffin11 апр. 2012 г., 16:35
Правильный, но бесполезный ответ будет "IEEE 754".
 Kendall Frey11 апр. 2012 г., 16:34
Они приходят из диапазона типа с плавающей точкой.
 foo11 апр. 2012 г., 16:59
Требуется ли стандарт IEEE 754 для стандарта C?
 SirGuy11 апр. 2012 г., 16:35
Вы имеете в виду, почему существуют ограничения этих значений?
 AProgrammer11 апр. 2012 г., 17:14
@foo, форматы IEEE 754 распространены, и некоторые книги склонны не делать различий между характеристиками реализации и требуемым языком, а некоторые люди склонны не обращать внимания, когда в книге ясно, что она показывает характеристику одной или нескольких распространенных реализаций, которые не требуются языком.

Ответы на вопрос(6)

32 бита для представления числа, которое выделяется следующим образом:

1 бит: знаковый бит

8 бит: показатель степени p

23 бита: мантисса

Экспонента хранится какp + BIAS где BIAS равен 127, мантисса имеет 23 бита и 24-й скрытый бит, который предполагается равным 1. Этот скрытый бит является старшим значащим битом (MSB) мантиссы, и показатель степени должен быть выбран так, чтобы он равнялся 1.

Это означает, что наименьшее число, которое вы можете представить,01000000000000000000000000000000 который1x2^-126 = 1.17549435E-38.

Наибольшее значение011111111111111111111111111111111мантисса равна 2 * (1 - 1/65536), а показатель степени равен 127, что дает(1 - 1 / 65536) * 2 ^ 128 = 3.40277175E38.

Те же самые принципы применяются к двойной точности, кроме битов:

1 бит: знаковый бит

11 битов: экспонентные биты

52 бита: биты мантиссы

BIAS: 1023

Таким образом, технически ограничения взяты из стандарта IEEE-754 для представления чисел с плавающей запятой, и как это происходит

 13 нояб. 2018 г., 14:16
Стоит отметить, что это наименьший нормальный, есть меньшие субнормалы:stackoverflow.com/a/53204544/895245
Решение Вопроса

IEEE-754 стандарт, который определяет стандартное представление чисел с плавающей запятой. Статья в Википедии по ссылкеобъясняет как достичь этих диапазонов, зная количество бит, используемых для знаков, мантиссы и показателя степени.

как, например, в IEEE 754. Вы можете проверить размеры с FLT_MAX, FLT_MIN, DBL_MAX, DBL_MIN в float.h.

 30 дек. 2017 г., 12:51
те, которые не доступны в пределах.
 11 июл. 2014 г., 21:55
эти макросы являются стандартными C-макросами? Почему я спрашиваю, INT_MAX и INT_MIN доступны в limit.h.

ую экспоненту (хотя используется от -126 до 127), поэтому самое большое число, которое вы можете представить:

(1 + 1 / 2 + ... 1 / (2 ^ 23)) * (2 ^ 127) = 
(2 ^ 23 + 2 ^ 23 + .... 1) * (2 ^ (127 - 23)) = 
(2 ^ 24 - 1) * (2 ^ 104) ~= 3.4e38
 13 нояб. 2018 г., 14:20
Здесь я объясняю, почему странный-126 в127 диапазон, который содержит только 253 числа, а не ожидаемые 255 (одно для бесконечности, а остальные - ненормальные):stackoverflow.com/a/53204544/895245

числа получены из того, как числа с плавающей запятой представлены в IEEE-754, и у Андреаса есть хорошая разбивка математики.

Однако следует помнить, что точность чисел с плавающей запятой не составляет точно 6 или 15 значащих десятичных цифр, как показано в таблице, поскольку точность чисел IEEE-754 зависит от количества значащих двоичных цифр.

float has 24 significant binary digits - which depending on the number represented translates to 6-8 decimal digits of precision.

double has 53 significant binary digits, which is approximately 15 decimal digits.

Еще один мой ответ есть дополнительные объяснения, если вы заинтересованы.

Infinity, NaN and subnormals

Это важные предостережения, о которых ни один другой ответ не упомянул.

Сначала прочтите это введение в IEEE 754 и ненормальные числа:Что такое субнормальное число с плавающей точкой?

Затем для одинарной точности (32-разрядных):

IEEE 754 says that if the exponent is all ones (0xFF == 255), then it represents either NaN or Infinity.

This is why the largest non-infinite number has exponent 0xFE == 254 and not 0xFF.

Then with the bias, it becomes:

254 - 127 == 127

FLT_MIN is the smallest normal number. But there are smaller subnormal ones! Those take up the -127 exponent slot.

Все утверждения следующей программы проходят на Ubuntu 18.04 amd64:

#include <assert.h>
#include <float.h>
#include <inttypes.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>

float float_from_bytes(
    uint32_t sign,
    uint32_t exponent,
    uint32_t fraction
) {
    uint32_t bytes;
    bytes = 0;
    bytes |= sign;
    bytes <<= 8;
    bytes |= exponent;
    bytes <<= 23;
    bytes |= fraction;
    return *(float*)&bytes;
}

int main(void) {
    /* All 1 exponent and non-0 fraction means NaN.
     * There are of course many possible representations,
     * and some have special semantics such as signalling vs not.
     */
    assert(isnan(float_from_bytes(0, 0xFF, 1)));
    assert(isnan(NAN));
    printf("nan                  = %e\n", NAN);

    /* All 1 exponent and 0 fraction means infinity. */
    assert(INFINITY == float_from_bytes(0, 0xFF, 0));
    assert(isinf(INFINITY));
    printf("infinity             = %e\n", INFINITY);

    /* ANSI C defines FLT_MAX as the largest non-infinite number. */
    assert(FLT_MAX == 0x1.FFFFFEp127f);
    /* Not 0xFF because that is infinite. */
    assert(FLT_MAX == float_from_bytes(0, 0xFE, 0x7FFFFF));
    assert(!isinf(FLT_MAX));
    assert(FLT_MAX < INFINITY);
    printf("largest non infinite = %e\n", FLT_MAX);

    /* ANSI C defines FLT_MIN as the smallest non-subnormal number. */
    assert(FLT_MIN == 0x1.0p-126f);
    assert(FLT_MIN == float_from_bytes(0, 1, 0));
    assert(isnormal(FLT_MIN));
    printf("smallest normal      = %e\n", FLT_MIN);

    /* The smallest non-zero subnormal number. */
    float smallest_subnormal = float_from_bytes(0, 0, 1);
    assert(smallest_subnormal == 0x0.000002p-126f);
    assert(0.0f < smallest_subnormal);
    assert(!isnormal(smallest_subnormal));
    printf("smallest subnormal   = %e\n", smallest_subnormal);

    return EXIT_SUCCESS;
}

GitHub upstream.

Скомпилируйте и запустите с:

gcc -ggdb3 -O0 -std=c11 -Wall -Wextra -Wpedantic -Werror -o subnormal.out subnormal.c
./subnormal.out

Выход:

nan                  = nan
infinity             = inf
largest non infinite = 3.402823e+38
smallest normal      = 1.175494e-38
smallest subnormal   = 1.401298e-45

Ваш ответ на вопрос