Каковы преимущества и недостатки использования одного вместо другого в C ++?
Что я должен использовать: double или float?
Ответы (11)
Если вы хотите узнать истинный ответ, прочтите What Каждый компьютерный ученый должен знать об арифметике с плавающей запятой.
Короче говоря, хотя double
допускает более высокую точность в своем представлении, для некоторых вычислений это приведет к большим ошибкам. «Правильный» выбор: используйте столько точности, сколько вам нужно, но не больше и выберите правильный алгоритм.
Многие компиляторы в любом случае выполняют расширенную математику с плавающей запятой в «нестрогом» режиме (т.е. используют более широкий тип с плавающей запятой, доступный в оборудовании, например, 80-битные и 128-битные с плавающей запятой), это также следует учитывать. На практике вы почти не заметите разницы в скорости - они в любом случае являются «родственными» аппаратными средствами.
double
- в большинстве случаев это безопаснее.
- person J-16 SDiZ; 03.07.2009
Если у вас нет особых причин поступить иначе, используйте double.
Возможно, что удивительно, это double, а не float, который является «нормальным» типом с плавающей запятой в C (и C ++). Стандартные математические функции, такие как sin и log, принимают двойные значения в качестве аргументов и возвращают двойные значения. Обычный литерал с плавающей запятой, например, когда вы пишете в своей программе 3.14, имеет тип double. Не плавают.
На типичных современных компьютерах удвоение может выполняться так же быстро, как и float, или даже быстрее, поэтому производительность обычно не является фактором, который следует учитывать даже при больших вычислениях. (И это должны быть большие вычисления, иначе производительность даже не должна приходить вам в голову. Мой новый настольный компьютер i7 может сделать шесть миллиардов умножений удвоений за одну секунду.)
На этот вопрос невозможно ответить, поскольку у вопроса нет контекста. Вот несколько вещей, которые могут повлиять на выбор:
- # P2 #
# P3 #
# P4 # Наличие FPU. Не все процессоры имеют FPU, и иногда типы с плавающей запятой эмулируются, а иногда типы с плавающей запятой просто не поддерживаются.
Архитектура FPU. FPU IA32 внутренне 80-битный - 32-битные и 64-битные числа с плавающей запятой расширяются до 80 бит при загрузке и уменьшаются при хранении. Также есть SIMD, который может параллельно выполнять четыре 32-битных или два 64-битных числа с плавающей запятой. Использование SIMD не определено в стандарте, поэтому потребуется компилятор, который выполняет более сложный анализ, чтобы определить, можно ли использовать SIMD, или требует использования специальных функций (библиотек или встроенных функций). Результатом 80-битного внутреннего формата является то, что вы можете получить несколько разные результаты в зависимости от того, как часто данные сохраняются в ОЗУ (что приводит к потере точности). По этой причине компиляторы не особенно хорошо оптимизируют код с плавающей запятой.
Пропускная способность памяти. Если для типа double требуется больше памяти, чем для числа с плавающей запятой, чтение данных займет больше времени. Это наивный ответ. На современном IA32 все зависит от того, откуда берутся данные. Если он находится в кэше L1, нагрузка незначительна при условии, что данные поступают из одной строки кеша. Если он занимает более одной строки кэша, возникают небольшие накладные расходы. Если он из L2, это займет немного больше времени, если он в ОЗУ, то еще дольше и, наконец, если он на диске, это огромное время. Таким образом, выбор типа float или double менее важен, чем способ использования данных. Если вы хотите выполнить небольшой расчет для большого количества последовательных данных, предпочтительнее использовать небольшой тип данных. Выполнение большого количества вычислений на небольшом наборе данных позволит вам использовать более крупные типы данных со значительным эффектом. Если вы обращаетесь к данным очень случайным образом, то выбор размера данных не имеет значения - данные загружаются в страницы / строки кеша. Таким образом, даже если вам нужен только байт из ОЗУ, вы можете передать 32 байта (это очень зависит от архитектуры системы). Вдобавок ко всему, CPU / FPU может быть суперскалярным (то есть конвейерным). Таким образом, даже если загрузка может занять несколько циклов, CPU / FPU может быть занят чем-то другим (например, умножением), что в некоторой степени скрывает время загрузки.
Стандарт не требует какого-либо конкретного формата для значений с плавающей запятой.
Если у вас есть технические характеристики, они помогут вам сделать оптимальный выбор. В противном случае решать, что использовать, остается только на собственном опыте.
Double более точен, но кодируется 8 байтами. float составляет всего 4 байта, поэтому меньше места и меньше точности.
Вы должны быть очень осторожны, если в вашем приложении есть double и float. Из-за этого у меня раньше была ошибка. Одна часть кода использовала float, а остальная часть кода использовала double. Копирование double в float, а затем float в double может вызвать ошибку точности, которая может иметь большое влияние. В моем случае это был химический завод ... надеюсь, драматических последствий это не имело :)
Я думаю, что именно из-за этого бага несколько лет назад взорвалась ракета Ariane 6 !!!
Тщательно продумайте тип, который будет использоваться для переменной.
Я лично все время иду на удвоение, пока не вижу узких мест. Затем я подумываю о переходе на плавающую или оптимизацию какой-либо другой части.
Это зависит от того, как компилятор реализует double. Допустимо, чтобы double и float были одного и того же типа (и это есть в некоторых системах).
При этом, если они действительно разные, то главный вопрос - точность. Двойник имеет гораздо более высокую точность из-за разницы в размере. Если используемые вами числа обычно превышают значение числа с плавающей запятой, используйте число типа double.
Некоторые другие люди упомянули о проблемах с производительностью. Это было бы последним в моем списке соображений. Правильность должна быть вашим соображением №1.
Используйте любую точность, которая требуется для достижения соответствующих результатов. Если вы обнаружите, что ваш код работает не так хорошо, как хотелось бы (вы правильно использовали профилирование?), Взгляните на:
- Справочное руководство по оптимизации архитектур Intel 64 и IA-32
- Оптимизация программного обеспечения для процессора AMD64
Я думаю, независимо от различий (которые, как все отмечают, с плавающей запятой занимают меньше места и в целом быстрее) ... кто-нибудь когда-либо сталкивался с проблемами производительности при использовании double? Я говорю: используйте double ... и если позже вы решите: "Вау, это действительно медленно" ... найдите узкое место в производительности (что, вероятно, не тот факт, что вы использовали double). ЗАТЕМ, если он все еще слишком медленный для вас, посмотрите, где вы можете пожертвовать некоторой точностью и использовать float.
Основное различие между float и double - точность. В Википедии есть дополнительная информация о одинарной точности (с плавающей запятой) и Двойная точность.
Это сильно зависит от процессора, наиболее очевидный компромисс между точностью и памятью. С ГБ ОЗУ память не представляет большой проблемы, поэтому обычно лучше использовать double
s.
Что касается производительности, то она сильно зависит от процессора. float
s обычно дает лучшую производительность, чем double
s на 32-битной машине. В 64-битной версии double
s иногда быстрее, поскольку это (обычно) собственный размер. Тем не менее, гораздо больше, чем ваш выбор типов данных, будет иметь значение, сможете ли вы воспользоваться инструкциями SIMD на своем процессоре.
double имеет более высокую точность, тогда как числа с плавающей запятой занимают меньше памяти и работают быстрее. В общем, вы должны использовать float, если у вас нет случая, когда он недостаточно точен.