В чем разница между float, _Float32, _Float32x и _Float32_t?
C23 представил ряд типов с плавающей запятой, включая, помимо прочего:
-
_Float32x
-
_Float32_t
Я не уверен в различиях, таких как:
- Это ключевые слова, псевдонимы типов или что-то еще?
- Являются ли они разными типами или могут быть псевдонимами ?
- Какова минимальная дальность и точность этих типов?
- Должны ли они соответствовать стандарту IEEE-754 (или IEC 60559)?
- Является
float
устарел_Float32
или другие типы?
Те же вопросы касаются_Float64
противdouble
, и_Float128
противlong double
.
1 ответ
Только типы (например ) являются псевдонимами из<math.h>
заголовок. Все остальные типы должны быть разными, а их имена являются ключевыми словами. (См. H.5.1 [Ключевые слова] ).
Все типы попадают в одну из четырех категорий (см. ниже). Выбирайте между ними следующим образом:
- , , и , если вас устраивают очень мягкие требования этих типов
- в качестве альтернативы проверьте, определены ли они, что делает их более строгими
- также используйте и, если вас устраивает, что они одного типа 1)
- Кроме того, вы должны использовать эти типы для совместимости с компиляторами до C23.
- если вам нужен определенный тип IEC60559 ровно с N битами
- если вам нужен расширенный тип IEC60559 с минимальной точностью
N
- особенно, если вы хотите хранить N -битные целые числа в числе с плавающей запятой без потерь
- если вам не нужны типы IEC60559, и вас не устраивают минимальные требования к и
1) На архитектурах без FPU двойной точности и могут быть того же размера (например, Arduino). Используйте другие типы (например, over ), если вместо этого вам нужна программная эмуляция двойной точности.
Стандартные плавающие типы
, , и вместе называются стандартными плавающими типами . Их представление определяется реализацией, но, тем не менее, существуют некоторые требования:
- должен быть в состоянии представлять любой и должен представлять любой
- if определен и представлен как и
- они должны быть способны представлять некоторое количество десятичных цифр без потерь и иметь минимальное/максимальное значение.
Обычно и являются иbinary64 соответственно и представляют , или представленное так же, как собойbinary12880-битное расширенное число с плавающей запятой x87
См. Стандарт C23 – E [Ограничения реализации]
Обмен плавающими типами
и т. д. являются так называемыми плавающими типами обмена . Их представление должно соответствовать формату обмена IEC60559 для двоичных чисел с плавающей запятой, например, типамиbinar32binary32 , .binary64 и т. д. Любые типы должны иметь ширину ровно N бит.
Типы и могут не существовать, если реализация не определяет и . Если так:
- существует, и
float
имеет тот же размер и выравнивание, что и он (но это отдельный тип) -
_Float64
существует и имеет тот же размер и выравнивание, что и он (но это отдельный тип) - более широкий
_FloatN
(обычно_Float128
) существует, если является типомbinaryN с N > 64
См. Стандарт C23 – H.2.1 [Обмен плавающими типами] .
Расширенные плавающие типы
, и т. д. являются так называемыми расширенными плавающими типами (названными в честь расширенной точности IEC60559 ). В отличие от своих аналогов по обмену, у них есть только минимальные требования к их представлению, а не точные требования. А_FloatNx
должен иметь ≥ N бит точности, что позволяет ему представлять N -битные целые числа без потерь.
Эти типы могут не существовать, если реализация не определяет__STDC_IEC_60559_TYPES__
. Если так:
-
_Float32x
существует, если__STDC_IEC_60559_BFP__
определен и может иметь тот же формат, что иdouble
(но это отдельный тип) -
_Float64x
существует, если__STDC_IEC_60559_DFP__
определен и может иметь тот же формат, что иlong double
(но это отдельный тип) - в любом случае,
_Float128x
опционально существует
Дополнительная точность и диапазон часто уменьшают ошибку округления и устраняют переполнение и потерю значения в промежуточных вычислениях.
См. Стандарт C23 – H.2.3 [Расширенные плавающие типы]
Псевдонимы
, и т. д. являются псевдонимами других плавающих типов , поэтому:
-
_FloatN_t
имеет как минимум диапазон и точность соответствующего реального плавающего типа (например, имеет как минимум диапазон и точность_Float32
если он существует) - более широкий тип может представлять все значения более узкого типа (например,
_Float64_t
может представлять_Float32_t
)
См. Стандарт C23 — H.11 [Математика &lt;math.h&gt;].