Чем отличаются типы данных float и double
Одинарная или двойная точность?
Введение
Статья также написана для тех из вас, у кого много данных. Если вам требуется несколько чисел тут или там, просто используйте double и не забивайте себе голову!
Точность данных
У 32-битных чисел с плавающей запятой точность примерно 24 бита, то есть около 7 десятичных знаков, а у чисел с двойной точностью — 53 бита, то есть примерно 16 десятичных знаков. Насколько это много? Вот некоторые грубые оценки того, какую точность вы получаете в худшем случае при использовании float и double для измерения объектов в разных диапазонах:
Почему всегда не хранить всё с двойной точностью?
Влияние на производительность вычислений с одинарной и двойной точностью
Когда производить вычисления с увеличенной точностью
Даже если вы храните данные с одинарной точностью, в некоторых случаях уместно использовать двойную точность при вычислениях. Вот простой пример на С:
Если вы запустите этот код на десяти числах одинарной точности, то не заметите каких-либо проблем с точностью. Но если запустите на миллионе чисел, то определённо заметите. Причина в том, что точность теряется при сложении больших и маленьких чисел, а после сложения миллиона чисел, вероятно, такая ситуация встретится. Практическое правило такое: если вы складываете 10^N значений, то теряете N десятичных знаков точности. Так что при сложении тысячи (10^3) чисел теряются три десятичных знака точности. Если складывать миллион (10^6) чисел, то теряются шесть десятичных знаков (а у float их всего семь!). Решение простое: вместо этого выполнять вычисления в формате double :
Пример
Предположим, что вы хотите точно измерить какое-то значение, но ваше измерительное устройство (с неким цифровым дисплеем) показывает только три значимых разряда. Измерение переменной десять раз выдаёт следующий ряд значений:
Чтобы увеличить точность, вы решаете сложить результаты измерений и вычислить среднее значение. В этом примере используется число с плавающей запятой в base-10, у которого точность составляет точно семь десятичных знаков (похоже на 32-битный float ). С тремя значимыми разрядами это даёт нам четыре дополнительных десятичных знака точности:
В сумме уже четыре значимых разряда, с тремя свободными. Что если сложить сотню таких значений? Тогда мы получим нечто вроде такого:
Всё ещё остались два неиспользованных разряда. Если суммировать тысячу чисел?
Пока что всё хорошо, но теперь мы используем все десятичные знаки для точности. Продолжим складывать числа:
Заметьте, как мы сдвигаем меньшее число, чтобы выровнять десятичный разделитель. У нас больше нет запасных разрядов, и мы опасно приблизились к потере точности. Что если сложить сто тысяч значений? Тогда добавление новых значений будет выглядеть так:
Обратите внимание, что последний значимый разряд данных (2 в 3.12) теряется. Вот теперь потеря точности действительно происходит, поскольку мы непрерывно будем игнорировать последний разряд точности наших данных. Мы видим, что проблема возникает после сложения десяти тысяч чисел, но до ста тысяч. У нас есть семь десятичных знаков точности, а в измерениях имеются три значимых разряда. Оставшиеся четыре разряда — это четыре порядка величины, которые выполняют роль своеобразного «числового буфера». Поэтому мы можем безопасно складывать четыре порядка величины = 10000 значений без потери точности, но дальше возникнут проблемы. Поэтому правило следующее:
(Существуют численно стабильные способы сложения большого количества значений. Однако простое переключение с float на double гораздо проще и, вероятно, быстрее).
Выводы
Приложение: Что такое число с плавающей запятой?
Я обнаружил, что многие на самом деле не вникают, что такое числа с плавающей запятой, поэтому есть смысл вкратце объяснить. Я пропущу здесь мельчайшие детали о битах, INF, NaN и поднормалях, а вместо этого покажу несколько примеров чисел с плавающей запятой в base-10. Всё то же самое применимо к двоичным числам.
Вот несколько примеров чисел с плавающей запятой, все с семью десятичными разрядами (это близко к 32-битному float ).
1.875545 · 10^-18 = 0.000 000 000 000 000 001 875 545
3.141593 · 10^0 = 3.141593
2.997925 · 10^8 = 299 792 500
6.022141 · 10^23 = 602 214 100 000 000 000 000 000
Выделенная жирным часть называется мантиссой, а выделенная курсивом — экспонентой. Вкратце, точность хранится в мантиссе, а величина в экспоненте. Так как с ними работать? Ну, умножение производится просто: перемножаем мантисссы и складываем экспоненты:
Сложение немного хитрее: чтобы сложить два числа разной величины, сначала нужно сдвинуть меньшее из двух чисел таким образом, чтобы запятая находилась в одном и том же месте.
Заметьте, как мы сдвинули некоторые из значимых десятичных знаков, чтобы запятые совпадали. Другими словами, мы теряем точность, когда складываем числа разных величин.
Разница между float и double
В программировании требуется хранить данные. Данные хранятся в памяти. Ячейки памяти, в которых хранятся данные, называются переменными. Каждая ячейка памяти может хранить определенный тип данных. Раз
Содержание:
Что такое поплавок?
Число с плавающей запятой представляет собой 32-битное число с плавающей запятой одинарной точности. Это предопределенный тип данных, поддерживаемый такими языками программирования, как Java. Для объявления переменной типа float используется ключевое слово float. Поэтому его нельзя использовать для имен идентификаторов, таких как имена методов и имена переменных. Обратитесь к программе ниже.
Что двойное?
Приведение типов может выполняться для типов данных. Это процесс преобразования одного типа данных в другой тип данных. При назначении меньшего типа данных большему типу данных преобразование не требуется. Расширение происходит в байтовом, коротком, int, long, float, двойном порядке. При назначении большего типа данных малому типу данных необходимо выполнить приведение.
X и y могут хранить двойные типы данных. Суммирование присваивается переменной z. Он также может хранить двойной. Приведение типов требуется, чтобы назначить больший тип данных меньшему типу данных. Следовательно, чтобы сохранить значение типа double в переменной с плавающей запятой, необходимо выполнить приведение типа, потому что тип данных double больше, чем тип float.
В чем сходство между float и double?
В чем разница между float и double?
float vs double
Урок №33. Типы данных с плавающей точкой: float, double и long double
Обновл. 11 Сен 2021 |
Типы данных с плавающей точкой
Есть три типа данных с плавающей точкой: float, double и long double. Язык C++ определяет только их минимальный размер (как и с целочисленными типами). Типы данных с плавающей точкой всегда являются signed (т.е. могут хранить как положительные, так и отрицательные числа).
Тип | Минимальный размер | Типичный размер | |
Тип данных с плавающей точкой | float | 4 байта | 4 байта |
double | 8 байт | 8 байт | |
long double | 8 байт | 8, 12 или 16 байт |
Объявление переменных разных типов данных с плавающей точкой:
Если нужно использовать целое число с переменной типа с плавающей точкой, то тогда после этого числа нужно поставить разделительную точку и нуль. Это позволяет различать переменные целочисленных типов от переменных типов с плавающей запятой:
Обратите внимание, литералы типа с плавающей точкой по умолчанию относятся к типу double. f в конце числа означает тип float.
Экспоненциальная запись
Обычно, в экспоненциальной записи, в целой части находится только одна цифра, все остальные пишутся после разделительной точки (в дробной части).
На практике экспоненциальная запись может использоваться в операциях присваивания следующим образом:
Вещественные типы (double, float)
Вещественные типы (или типы с плавающей точкой) представляют значения, имеющие дробную часть. В языке MQL5 есть два типа для чисел с плавающей точкой. Способ представления вещественных чисел в машинной памяти определен стандартом IEEE 754 и не зависит от платформ, операционных систем и языков программирования.
Минимальное положительное значение
Константы с плавающей точкой состоят из целой части, точки (.) и дробной части. Целая и дробная части представляют собой последовательности десятичных цифр.
double a= 12.111 ;
double b=- 956.1007 ;
float c = 0.0001 ;
float d = 16 ;
Существует научный способ записи вещественных констант, зачастую этот способ записи более компактный, чем традиционный.
Необходимо помнить, что вещественные числа хранятся в памяти компьютера с некоторой ограниченной точностью в двоичной системе счисления, в то время как общепринятой в использовании является десятичная система счисления. Поэтому многие числа, которые точно записываются в десятичной системе, в двоичной системе можно записать только в виде бесконечной дроби.
Например, числа 0.3 и 0.7 представлены в компьютере бесконечными дробями, в то время как число 0.25 хранится точно, так как представляет из себя степень двойки.
В связи с этим, категорически не рекомендуется сравнивать между собой два вещественных числа на равенство, так как такое сравнение не является корректным.
Если все же необходимо сравнить на равенство два вещественных числа, то можно сделать это двумя разными способами. Первый способ заключается в сравнении разницы между двумя числами с какой-то малой величиной, задающей точность сравнения.
Второй способ предполагает сравнивать нормализованную разность двух вещественных чисел с нулевым значением. Сравнивать разность нормализованных чисел с нулём бесполезно, так как в результате любой математической операции с нормализованными числами результат получается ненормализованным.
В результате некоторых операций математического сопроцессора может получиться недействительное вещественное число, которое нельзя использовать в математических операциях и операциях сравнения, так как результат выполнения операций над недействительными вещественными числами неопределен. Например, при попытке вычислить арксинус от 2, результатом будет минус бесконечность.
Кроме минус бесконечности существуют плюс бесконечность и NaN (не число). Чтобы определить, что данное число недействительно, можно использовать функцию MathIsValidNumber(). По стандарту IEEE они имеют специальное машинное представление. Например, плюс бесконечность для типа double имеет битовое представление 0x7FF0 0000 0000 0000.
Чем отличаются типы данных float и double
Как хранятся действительные числа в компьютере
Для хранения действительных чисел в памяти компьютера отводится определённое количество бит. Действительное число хранится в виде знака (плюс или минус), мантиссы и экспоненты. Что такое мантисса и экспонента лучше объяснить на примере: масса Земли равна 5.972*10 24 килограмм. Здесь 5.972 — мантисса, а 24 — экспонента.
При выводе больших (или очень маленьких) чисел в программе на C++ можно увидеть на экране запись типа 5.972E23. Сначала выводится мантисса, затем — буква E, а затем — экспонента. Запись представлена в десятичной системе счисления. В таком же формате можно вводить большие или очень маленькие действительные числа. Этот формат называется экспоненциальной записью числа.
Мы будем работать с типом double (с числами двойной точности), который занимает 8 байт. Один бит отводится под знак числа, 11 под экспоненту и 52 под мантиссу. С помощью 52 бит можно хранить числа длиной до 15-16 десятичных цифр. Таким образом, независимо от того, какая у числа экспонента, правильные значения будут иметь только первые 15 цифр. В примере с массой Земли точно заданы первые 4 цифры, таким образом, погрешность составляет 10 20 килограмм. Это довольно большая погрешность. Чтобы масса Земли с точностью до первых четырёх знаков изменилась, на неё нужно дополнительно поселить миллиард миллиардов довольно упитанных людей.
Таким образом, можно сказать, что числа в компьютере хранятся не с абсолютной, а с относительной погрешностью (то есть погрешность зависит от значения хранимого числа).
То, что числа хранятся неточно, создаёт нам множество проблем.
Итак, мы рассмотрели главные моменты, касающиеся основных типов данных в С++. Осталось только показать, откуда взялись все эти диапазоны принимаемых значений и размеры занимаемой памяти. А для этого разработаем программу, которая будет вычислять основные характеристики всех, выше рассмотренных, типов данных.