Типы с плавающей запятой фиксированного размера

92

В заголовках stdint.h(C99), boost / cstdint.hpp и cstdint(C ++ 0x), среди прочего, есть тип int32_t.

Существуют ли аналогичные типы с плавающей запятой фиксированного размера? Что-то вроде float32_t?

Пьетро
источник
4
Зачем тебе что-то подобное?
AraK,
41
Вам нужно что-то подобное, когда у вас есть структура данных со значением с плавающей запятой, и вы также хотите точно знать, каков ее размер.
моб
5
@mobrule: Если вам просто нужно знать, какой размер, вы используете sizeofоператор. Такой тип был бы полезен, когда алгоритм требует, чтобы он был известного определенного размера.
Стивен Кэнон,
6
@Stephen Canon - да, если вы хотите гарантировать, какой размер. Скажем, экземпляр вашей структуры данных умещается в 64 бита и может быть передан по значению в некоторую внешнюю библиотеку.
моб
7
@StephenCanon Рассмотрим кроссплатформенную библиотеку сериализации. Как можно sizeofиспользовать для решения проблемы последовательного маршалинга и демаршалинга плавающих типов?
Kyle Strand

Ответы:

48

Ничего подобного в настоящее время не существует в стандартах C или C ++. Фактически, нет даже гарантии, что floatвообще будет двоичный формат с плавающей запятой.

Некоторые компиляторы гарантируют, что floatтипом будет 32-битный двоичный формат IEEE-754. Некоторые этого не делают. На самом floatделе это singleтип IEEE-754 на большинстве невстроенных платформ, хотя применяются обычные предостережения о некоторых компиляторах, оценивающих выражения в более широком формате.

Существует рабочая группа, обсуждающая добавление привязок к языку C для версии IEEE-754 2008 г., которая могла бы рекомендовать добавить такой typedef. Если бы это было добавлено в C, я ожидаю, что стандарт C ++ последует этому примеру ... в конце концов.

Стивен Кэнон
источник
3
Независимо от IEEE-754 или нет, это все равно не предотвратит проблемы с переносимостью endian.
Mark B
1
@Pietro: изменение языка не повлияет на совместимость вашего оборудования, это только помешает некоторому оборудованию соответствовать требованиям. Как IEEE FP может гарантировать переносимость?
Potatoswatter
1
@Potatoswatter: Это побудит производителей оборудования предоставлять соответствующие решения. Если часть a поддерживает стандартный C без необходимости использования библиотеки soft-float, а часть b - нет, это рыночное преимущество для части a.
Стивен Кэнон,
2
@Potatoswatter: (Почти) никого не волнует скорость оборудования. Мы заботимся о скорости работы программного обеспечения на оборудовании. Программное обеспечение может работать быстрее, если оборудование, на котором оно работает, соответствует стандартам, и ему не нужно выявлять и исправлять 15 различных особых случаев в зависимости от того, на какой платформе оно работает.
Стивен Кэнон,
8
Как, черт возьми, вы могли бы улучшить переносимость, предотвратив компиляцию вашего кода на нескольких нишевых архитектурах? Либо вы полагаетесь на то, что числа с плавающей запятой являются IEEE, и в этом случае ваш код уже будет работать в каждой IEEE-совместимой реализации и ни на чем другом, либо вы этого не сделаете, и в этом случае ваш код будет работать в более широком диапазоне систем. Если бы C ++ гарантировал соответствие IEEE, ваш код волшебным образом не стал бы более переносимым, вы бы просто исключили, что он когда-либо мог бы работать на этих несовместимых архитектурах. Ваша логика полностью обратная.
jalf
30

Если вы хотите узнать, floatявляется ли ваш тип 32-битным IEEE, проверьте std::numeric_limits<float>::is_iec559. Это константа времени компиляции, а не функция.

Если вы хотите быть более пуленепробиваемым, также std::numeric_limits<float>::digitsубедитесь, что они не скрытно используют стандарт двойной точности IEEE для float. Должно быть 24.

Когда дело доходит до long doubleпроверки, важнее, digitsпотому что существует пара форматов IEEE, которые могут быть разумными: 128 бит (цифры = 113) или 80 бит (цифры = 64).

Это было бы непрактично, float32_tпотому что вы обычно хотите использовать оборудование с плавающей запятой, если оно доступно, и не прибегать к программной реализации.

Potatoswatter
источник
long doubleФормат на OS X (32-бит и 64-битный Intel) в точности IEEE-754 с двойной расширенный формат хранится в мало-Endian порядке. Ничего особенного в этом нет. Байты 0-7 содержат поле значения, а байты 8 и 9 содержат поля экспоненты и знака.
Стивен Кэнон,
@ Стивен: это хорошие новости: v). Это согласуется с числами, которые я опубликовал?
Potatoswatter
1
Помните, что двойной расширенный (в отличие от других форматов 754) имеет явный ведущий бит значимости, поэтому 5.0Lимеет значение a000000000000000. Его несмещенный показатель степени равен +2, а смещение двойного расширенного показателя составляет 3fff, поэтому смещенный показатель для 5.0L равен 4001. Фактический байтовый образец при хранении в порядке прямого порядка байтов равен 00 00 00 00 00 00 00 a0 01 40, и если вы посмотрите на него как на два 64-битных целых числа с прямым порядком байтов, вы увидите именно то, что вы наблюдали.
Стивен Кэнон,
(*) двойное расширение, реализованное Intel в аппаратном обеспечении, то есть. Двойной расширенный формат на самом деле не закреплен так, как два других основных формата IEEE-754 (1985).
Стивен Кэнон,
@Stephen: Я почти уверен, что 4001в little-endian это 01 40 00 00 ...Если ничего больше, младший байт идет первым. Я действительно ожидаю, что последовательность a0 01 40появится где-то в номере (если они только выполнили вращение), но я не думаю, что вы объяснили, почему a0и 01 40находятся в совершенно разных частях.
Potatoswatter
18

Если вы считаете, что определение типов, таких как float32_t и float64_t, по каким-либо причинам нецелесообразно, вы, должно быть, слишком привыкли к своей знакомой ОС, компилятору, и не можете смотреть за пределы своего маленького гнезда.

Существует оборудование, которое изначально выполняет 32-битные операции с плавающей запятой IEEE и другое, которое выполняет 64-битные операции. Иногда таким системам даже приходится взаимодействовать друг с другом, и в этом случае чрезвычайно важно знать, является ли double 32-битным или 64-битным на каждой платформе. Если 32-битная платформа будет производить чрезмерные вычисления на основе 64-битных значений из другой, мы можем захотеть выполнить приведение с более низкой точностью в зависимости от требований к времени и скорости.

Мне лично неудобно использовать поплавки и удвоения, если я не знаю точно, сколько битов они находятся на моей платформе. Тем более, если я перенесу их на другую платформу через какой-то канал связи.

EmbeddedCoder
источник
«Я лично чувствую себя некомфортно, используя числа с плавающей запятой и удвоения, если я точно не знаю, сколько битов они находятся на моей платформе. Тем более, если я собираюсь передать их на другую платформу по какому-то каналу связи». - Вы имеете в виду, что используете форматы текстовых файлов? У них есть недостаток размера файла: для 32-битного числа с плавающей запятой требуется 4 байта; в текстовой форме они могут представлять только четырехзначные числа ...
Пьетро
3

В настоящее время предлагается добавить в язык следующие типы:

decimal32
decimal64
decimal128

которые однажды могут быть доступны через #include <decimal>.

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3871.html

Тревор Хики
источник
3
Конечно, десятичные типы не являются типами с плавающей запятой IEEE 754.
Майк Дезимоун
ПОДОЖДИТЕ! Нам decimal24также нужно упростить такие вещи, как чтение файлов wav с 24-битными образцами!
tjwrona1992