Что я должен использовать: double или float?

Каковы преимущества и недостатки использования одного вместо другого в C ++?


person AraK    schedule 02.07.2009    source источник
comment
Кто-нибудь пробовал создать массив чисел с плавающей запятой и массив чисел типа double и посмотреть, действительно ли 4 байта между членами на числах с плавающей запятой и 8 байтов между членами на числах типа double? Возможно, что 64-битный компилятор / компьютер все еще может зарезервировать 8 байтов на член для чисел с плавающей запятой, даже если им это не нужно.   -  person user3015682    schedule 29.10.2019


Ответы (11)


Если вы хотите узнать истинный ответ, прочтите What Каждый компьютерный ученый должен знать об арифметике с плавающей запятой.

Короче говоря, хотя double допускает более высокую точность в своем представлении, для некоторых вычислений это приведет к большим ошибкам. «Правильный» выбор: используйте столько точности, сколько вам нужно, но не больше и выберите правильный алгоритм.

Многие компиляторы в любом случае выполняют расширенную математику с плавающей запятой в «нестрогом» режиме (т.е. используют более широкий тип с плавающей запятой, доступный в оборудовании, например, 80-битные и 128-битные с плавающей запятой), это также следует учитывать. На практике вы почти не заметите разницы в скорости - они в любом случае являются «родственными» аппаратными средствами.

person J-16 SDiZ    schedule 02.07.2009
comment
да. С современными процессорами, которые предварительно выбирают все большие и большие блоки памяти, параллельными модулями числовой обработки и конвейерными архитектурами, проблема скорости действительно не является проблемой. Если вы имеете дело с огромным количеством чисел, возможно, разница в размере между 4-байтовым числом с плавающей запятой и 8-байтовым двойным может иметь значение в объеме памяти. - person lavinio; 02.07.2009
comment
Что ж, SSE (или любой другой модуль с плавающей запятой) сможет обрабатывать в два раза больше операций с одинарной точностью по сравнению с двойной точностью. Если вы используете только x87 (или любой скаляр) с плавающей запятой, это, вероятно, не имеет значения. - person Greg Rogers; 02.07.2009
comment
@ Грег Роджерс: компиляторы сейчас не настолько умны. Если вы не пишете необработанную сборку, больших различий нет. И да, это может измениться по мере развития компилятора. - person J-16 SDiZ; 03.07.2009
comment
Дополнительные примечания: если вы абсолютно не знаете, как выглядят данные (или просто не имеете ни малейшего представления о математических расчетах в ссылках), просто используйте double - в большинстве случаев это безопаснее. - person J-16 SDiZ; 03.07.2009
comment
@jokoon, нет ничего простого с плавающей запятой и всей проблемной области точности / числовой стабильности. - person vonbrand; 20.01.2013
comment
вы видите разницу в скорости в графических процессорах? - person Charlie Parker; 09.09.2020

Если у вас нет особых причин поступить иначе, используйте double.

Возможно, что удивительно, это double, а не float, который является «нормальным» типом с плавающей запятой в C (и C ++). Стандартные математические функции, такие как sin и log, принимают двойные значения в качестве аргументов и возвращают двойные значения. Обычный литерал с плавающей запятой, например, когда вы пишете в своей программе 3.14, имеет тип double. Не плавают.

На типичных современных компьютерах удвоение может выполняться так же быстро, как и float, или даже быстрее, поэтому производительность обычно не является фактором, который следует учитывать даже при больших вычислениях. (И это должны быть большие вычисления, иначе производительность даже не должна приходить вам в голову. Мой новый настольный компьютер i7 может сделать шесть миллиардов умножений удвоений за одну секунду.)

person Thomas Padron-McCarthy    schedule 25.09.2009

На этот вопрос невозможно ответить, поскольку у вопроса нет контекста. Вот несколько вещей, которые могут повлиять на выбор:

  1. # P2 #
    # P3 #
    # P4 #
  2. Наличие FPU. Не все процессоры имеют FPU, и иногда типы с плавающей запятой эмулируются, а иногда типы с плавающей запятой просто не поддерживаются.

  3. Архитектура FPU. FPU IA32 внутренне 80-битный - 32-битные и 64-битные числа с плавающей запятой расширяются до 80 бит при загрузке и уменьшаются при хранении. Также есть SIMD, который может параллельно выполнять четыре 32-битных или два 64-битных числа с плавающей запятой. Использование SIMD не определено в стандарте, поэтому потребуется компилятор, который выполняет более сложный анализ, чтобы определить, можно ли использовать SIMD, или требует использования специальных функций (библиотек или встроенных функций). Результатом 80-битного внутреннего формата является то, что вы можете получить несколько разные результаты в зависимости от того, как часто данные сохраняются в ОЗУ (что приводит к потере точности). По этой причине компиляторы не особенно хорошо оптимизируют код с плавающей запятой.

  4. Пропускная способность памяти. Если для типа double требуется больше памяти, чем для числа с плавающей запятой, чтение данных займет больше времени. Это наивный ответ. На современном IA32 все зависит от того, откуда берутся данные. Если он находится в кэше L1, нагрузка незначительна при условии, что данные поступают из одной строки кеша. Если он занимает более одной строки кэша, возникают небольшие накладные расходы. Если он из L2, это займет немного больше времени, если он в ОЗУ, то еще дольше и, наконец, если он на диске, это огромное время. Таким образом, выбор типа float или double менее важен, чем способ использования данных. Если вы хотите выполнить небольшой расчет для большого количества последовательных данных, предпочтительнее использовать небольшой тип данных. Выполнение большого количества вычислений на небольшом наборе данных позволит вам использовать более крупные типы данных со значительным эффектом. Если вы обращаетесь к данным очень случайным образом, то выбор размера данных не имеет значения - данные загружаются в страницы / строки кеша. Таким образом, даже если вам нужен только байт из ОЗУ, вы можете передать 32 байта (это очень зависит от архитектуры системы). Вдобавок ко всему, CPU / FPU может быть суперскалярным (то есть конвейерным). Таким образом, даже если загрузка может занять несколько циклов, CPU / FPU может быть занят чем-то другим (например, умножением), что в некоторой степени скрывает время загрузки.

  5. Стандарт не требует какого-либо конкретного формата для значений с плавающей запятой.

Если у вас есть технические характеристики, они помогут вам сделать оптимальный выбор. В противном случае решать, что использовать, остается только на собственном опыте.

person Skizz    schedule 02.07.2009

Double более точен, но кодируется 8 байтами. float составляет всего 4 байта, поэтому меньше места и меньше точности.

Вы должны быть очень осторожны, если в вашем приложении есть double и float. Из-за этого у меня раньше была ошибка. Одна часть кода использовала float, а остальная часть кода использовала double. Копирование double в float, а затем float в double может вызвать ошибку точности, которая может иметь большое влияние. В моем случае это был химический завод ... надеюсь, драматических последствий это не имело :)

Я думаю, что именно из-за этого бага несколько лет назад взорвалась ракета Ariane 6 !!!

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

person luc    schedule 02.07.2009
comment
Обратите внимание, что 4/8 байтов для float / double даже не гарантируется, это будет зависеть от платформы. Это может быть даже один и тот же тип ... - person sleske; 22.02.2010
comment
Код Ariane 5 попытался преобразовать 64-битную плавающую точка, значение которой было больше 32 767, в 16-битовое целое число со знаком. Это сгенерировало исключение переполнения, которое заставило ракету инициировать последовательность самоуничтожения. Рассматриваемый код был кодом, который был повторно использован от более старой, меньшей ракеты. - person cmwt; 27.03.2019

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

person Eric    schedule 02.07.2009

Это зависит от того, как компилятор реализует double. Допустимо, чтобы double и float были одного и того же типа (и это есть в некоторых системах).

При этом, если они действительно разные, то главный вопрос - точность. Двойник имеет гораздо более высокую точность из-за разницы в размере. Если используемые вами числа обычно превышают значение числа с плавающей запятой, используйте число типа double.

Некоторые другие люди упомянули о проблемах с производительностью. Это было бы последним в моем списке соображений. Правильность должна быть вашим соображением №1.

person JaredPar    schedule 02.07.2009

Используйте любую точность, которая требуется для достижения соответствующих результатов. Если вы обнаружите, что ваш код работает не так хорошо, как хотелось бы (вы правильно использовали профилирование?), Взгляните на:

person user7116    schedule 02.07.2009

Я думаю, независимо от различий (которые, как все отмечают, с плавающей запятой занимают меньше места и в целом быстрее) ... кто-нибудь когда-либо сталкивался с проблемами производительности при использовании double? Я говорю: используйте double ... и если позже вы решите: "Вау, это действительно медленно" ... найдите узкое место в производительности (что, вероятно, не тот факт, что вы использовали double). ЗАТЕМ, если он все еще слишком медленный для вас, посмотрите, где вы можете пожертвовать некоторой точностью и использовать float.

person Tom    schedule 02.07.2009

Основное различие между float и double - точность. В Википедии есть дополнительная информация о одинарной точности (с плавающей запятой) и Двойная точность.

person Michaël Larouche    schedule 02.07.2009

Это сильно зависит от процессора, наиболее очевидный компромисс между точностью и памятью. С ГБ ОЗУ память не представляет большой проблемы, поэтому обычно лучше использовать doubles.

Что касается производительности, то она сильно зависит от процессора. floats обычно дает лучшую производительность, чем doubles на 32-битной машине. В 64-битной версии doubles иногда быстрее, поскольку это (обычно) собственный размер. Тем не менее, гораздо больше, чем ваш выбор типов данных, будет иметь значение, сможете ли вы воспользоваться инструкциями SIMD на своем процессоре.

person Zifre    schedule 02.07.2009

double имеет более высокую точность, тогда как числа с плавающей запятой занимают меньше памяти и работают быстрее. В общем, вы должны использовать float, если у вас нет случая, когда он недостаточно точен.

person Tal Pressman    schedule 02.07.2009
comment
На типичных современных компьютерах double работает так же быстро, как и float. - person Thomas Padron-McCarthy; 26.09.2009