Arduino.ru
Тип данных float служит для хранения чисел с плавающей запятой. Этот тип часто используется для операций с данными, считываемыми с аналоговых входов. Диапазон значений — от -3.4028235E+38 до 3.4028235E+38. Переменная типа float занимает 32 бита (4 байта) в памяти.
Тип float имеет точность 6-7 знаков, имеются ввиду все знаки, а не только мантисса. Обычно для увеличения точности используют другой тип — double, но на платформе Arduino, double и float имеют одинаковую точность.
Хранение в памяти чисел с плавающей точкой в двоичной системе обуславливает потерю точности. Так, например, 6.0 / 3.0 не обязательно равен 2.0. Сравнивая два числа с плавающей точкой следует проверять не точное равенство, а разницу между этими числами, меньше ли она некого выбранной малого порога.
Следует также учитывать, что арифметические операции над числами с плавающей запятой выполняются существенно медленнее, чем над целыми.
Пример
float myfloat; float sensorCalbrate = 1.117;
Синтаксис
float var = val;
- var — имя переменной
- val — присваиваемое значение
Пример использования в коде
int x; int y; float z; x = 1; y = x / 2; // y теперь равен 0, тип int не может хранить дробные числа z = (float)x / 2.0; // z равна .5 (следует использовать 2.0, а не 2)
Сколько бит(байт) занимают типы данных с плавающей запятой в C++?
Например,int занимает 4 байта,из-за этого,работая с этим типом данных,мы можем работать только с ограниченными по величине цифрами.Но в случае с double можно задать абсолютно любое число,да еще и указать множество цифр после запятой.Как это работает?
И еще,пользуясь случаем,хочу спросить: для чего в конце приписывают ‘f’ ,когда пользуются типом данных float?
- Вопрос задан более трёх лет назад
- 3918 просмотров
Комментировать
Решения вопроса 1
Программист на «си с крестами» и не только
Например, int занимает 4 байта
По современному консенсусу, да. Но иногда может занимать 2 байта (меньше — вроде нет).
В случае с double можно задать абсолютно любое число
double x = 1e500;
Ответ статического анализатора Clang: magnitude of floating-point constant is too large for type ‘double’; maximum is 1.79…E+308
На число 1.23456789012345678901234 не жалуется, но учите матчасть — относительная точность double 52 двоичных цифры (исключая головную единицу), или около 16 десятичных.
для чего в конце приписывают ‘f’ ,когда пользуются типом данных float?
Чтобы расчёт float x; return x + 12.34f вёлся в менее точном типе float, а не double.
А вот коду float x = 12.34; это совершенно не нужно, компилятор и сам поймёт, что преобразование double → float можно сделать при компиляции.
Сколько бит(байт) занимают типы данных с плавающей запятой в C++?
Зависит от машины, но по выработанному консенсусу — float 4, double 8.
Нестандартная (присущая x86) реализация long double имеет 10 значащих байтов, но 12 или 16 вместе с выравниванием.
Тип float
Числа с плавающей запятой используют формат IEEE (Института инженеров по электротехнике и электронике). Значения с одиночной точностью и типом float имеют 4 байта, состоят из бита знака, 8-разрядной двоичной экспоненты excess-127 и 23-битной мантиссы. Мантисса представляет число от 1,0 до 2,0. Поскольку бит высокого порядка мантиссы всегда равен 1, он не сохраняется в числе. Это представление обеспечивает для типа float диапазон примерно от 3,4E–38 до 3,4E+38.
Можно объявить переменные в качестве типа float или double в зависимости от нужд приложения. Основные различия между двумя типами значения заключаются в представляемой ими значимости, требуемых ресурсах хранения и диапазоне. В следующей таблице показана связь между значимостью и требованиями к хранению.
Типы с плавающей запятой
| Type | Значимые цифры | Число байтов |
|---|---|---|
| float | 6–7 | 4 |
| double | 15–16 | 8 |
Переменные с плавающей запятой представлены мантиссой, которая содержит значение числа, и экспонентой, которая содержит порядок возрастания числа.
В следующей таблице показано количество битов, выделенных мантиссе и экспоненте для каждого типа с плавающей запятой. Наиболее значимый бит любого типа float или double — всегда бит знака. Если он равен 1, число считается отрицательным; в противном случае — положительным.
Длина экспонент и мантисс
| Type | Длина экспоненты | Длина мантиссы |
|---|---|---|
| float | 8 бит | 23 бита |
| double | 11 бит | 52 бита |
Поскольку экспоненты хранятся в форме без знака, экспоненты смещены на половину своего возможного значения. Для типа float смещение составляет 127; для типа double это 1023. Можно вычислить фактическое значение экспоненты, вычтя значение смещения из значения экспоненты.
Мантисса хранится в виде бинарной доли, которая больше или равна 1 и меньше 2. Для типов float и double в мантиссе подразумевается наличие начального 1 в наиболее значимой битовой позиции, поэтому фактически длина мантисс составляет 24 и 53 бит соответственно, даже если наиболее значимый бит никогда не хранится в памяти.
Вместо только что описанного метода хранения пакет значений с плавающей запятой может хранить двоичные числа с плавающей запятой как денормализованные числа. Денормализованные числа — это ненулевые числа с плавающей запятой и зарезервированными значениями экспонент, в которых наиболее значимый бит мантиссы равен 0. Используя денормализованный формат, можно расширить диапазон числа с плавающей запятой в ущерб точности. Невозможно контролировать, в какой форме будет представлено число с плавающей запятой — нормализованной или денормализованной. Пакет значений с плавающей запятой определяет представление. В пакете значений с плавающей запятой никогда не используется денормализованная форма. Исключение составляют случаи, когда экспонента становится меньше, чем минимальное значение, которое может быть представлено в нормализованной форме.
В следующей таблице показаны минимальное и максимальное значения, которое можно сохранить в переменных каждого типа с плавающей запятой. Значения, указанные в этой таблице, применяются только к нормализованным числам с плавающей запятой; денормализованные числа с плавающей запятой имеют меньшее минимальное значение. Обратите внимание, что номера, сохраненные в регистрах 80x87, всегда представлены в 80-разрядной нормализованной форме; при сохранении в 32- или 64-разрядных переменных с плавающей запятой числа могут быть представлены только в ненормализованной форме (переменные типов float и long).
Диапазон типов с плавающей запятой
| Type | Минимальное значение | Максимальное значение |
|---|---|---|
| плавающее | 1,175494351 E – 38 | 3,402823466 E + 38 |
| double | 2,2250738585072014 E – 308 | 1,7976931348623158 E + 308 |
Если точность менее важна, чем размер хранимых данных, имеет смысл использовать тип float для переменных с плавающей запятой. И наоборот, если точность — наиболее важный критерий, используйте тип double.
Уровень переменных с плавающей запятой можно повысить до типа большей значимости (преобразование типа float в тип double). Повышение уровня часто происходит при выполнении арифметических действий с переменными плавающего типа. Это арифметическое действие всегда выполняется на том же уровне точности, что и переменная с наивысшим уровнем точности. Например, проанализируйте объявления следующих типов.
float f_short; double f_long; long double f_longer; f_short = f_short * f_long;
В предыдущем примере уровень переменной f_short повышается до типа double, а затем переменная умножается на f_long ; затем результат округляется до типа float и присваивается объекту f_short .
В следующем примере (с использованием объявлений из предыдущего примера) арифметическая операция выполняется на уровне точности переменной типа float (32-разрядной). Уровень результата затем повышается до уровня double.
f_longer = f_short * f_short;
Сколько «весят» типы данных
Все данные в языке Си имеют свой тип. Переменные определенных типов занимают в памяти какое-то место, разное в зависимости от типа. В Си нет четкого закрепления количества памяти за определенными типами. Это отдано на реализацию конкретного компилятора под конкретную платформу. Например, переменная типа int в одном компиляторе может занимать в памяти 16 бит, в другом — 32 бита, в третьем — 8 бит. Все определяет конкретный компилятор. Правда, все стремятся к универсализации, и в основном в большинстве компиляторов тип int, например, занимает 2 байта, а тип char — один.
Я в последнее время немного затупил, не мог вспомнить, сколько байт занимает тип double в AVR-GCC. Обычно при программировании контроллеров работаешь с целочисленными типами, типа int и char, а к типам с плавающей точкой прибегаешь не часто, в связи с их ресурсоемкостью.
Поэтому, на будущее, оставлю себе здесь памятку с указанием размеров занимаемой памяти типами данных для компилятора AVR-GCC и диапазон изменения переменных этого типа.
Типы данных в языке Си для компилятора AVR-GCC
| Тип | Размер в байтах (битах) |
Интервал изменения |
|---|---|---|
| char | 1 (8) | -128 .. 127 |
| unsigned char | 1 (8) | 0 .. 255 |
| signed char | 1 (8) | -128 .. 127 |
| int | 2 (16) | -32768 .. 32767 |
| unsigned int | 2 (16) | 0 .. 65535 |
| signed int | 2 (16) | -32768 .. 32767 |
| short int | 2 (16) | -32768 .. 32767 |
| unsigned short int | 2 (16) | 0 .. 65535 |
| signed short int | 2 (16) | -32768 .. 32767 |
| long int | 4 (32) | -2147483648 .. 2147483647 |
| unsigned long int | 4 (32) | 0 .. 4294967295 |
| signed long int | 4 (32) | -2147483648 .. 2147483647 |
| float | 4 (32) | 3.4Е-38 .. 3.4Е+38 |
| double | 4 (32) | 3.4Е-38 .. 3.4Е+38 |
| long double | 10 (80) | 3.4Е-4932 .. 3.4Е+4932 |
[stextbox caption=»Обратите внимание»]Реализация типа double в AVR-GCC отступает от стандарта. По стандарту double занимает 64 бита. В AVR-GCC переменная этого типа занимает 32 бита, и соответственно, она эквивалентна переменной с типом float![/stextbox]
В дополнение к этому, в библиотеках AVR-GCC введено несколько производных от стандартных типов. Они описаны в файле stdint.h. Сделано это, наверно, для улучшения наглядности и уменьшения текста программ (ускорения их написания :)). Вот табличка соответствия:
Производные типы от стандартных в языке Си для компилятора AVR-GCC
| Производный тип | Стандартный тип |
|---|---|
| int8_t | signed char |
| uint8_t | unsigned char |
| int16_t | signed int |
| uint16_t | unsigned int |
| int32_t | signed long int |
| uint32_t | unsigned long int |
| int64_t | signed long long int |
| uint64_t | unsigned long long int |
Тип Void
В языке Си есть еще один тип — тип void. Void используется для указания, что функция не возвращает ничего в качестве результата, или не принимает на вход никаких параметров. Этот тип не применяется для объявления переменных, соответственно он не занимает места в памяти.
