Каковы преимущества и недостатки использования одного вместо другого в C ++?
Каковы преимущества и недостатки использования одного вместо другого в C ++?
Ответы:
Если вы хотите узнать истинный ответ, вам следует прочитать « Что должен знать каждый компьютерный ученый об арифметике с плавающей точкой» .
Короче говоря, хотя и double
позволяет более высокую точность представления, для некоторых вычислений это приведет к большим ошибкам . «Правильный» выбор: используйте столько точности, сколько вам нужно, но не больше, и выберите правильный алгоритм .
Многие компиляторы в любом случае выполняют расширенную математику с плавающей запятой в «нестрогом» режиме (т. Е. Используют более широкий тип с плавающей запятой, доступный в оборудовании, например, 80-битные и 128-битные с плавающей запятой), это также следует учитывать. На практике разницы в быстродействии практически не видно - они все равно не железо.
double
- это в большинстве случаев безопаснее.
Если у вас нет особых причин поступить иначе, используйте double.
Возможно, удивительно, что это double, а не float, который является «нормальным» типом с плавающей запятой в C (и C ++). Стандартные математические функции, такие как sin и log, принимают двойные значения в качестве аргументов и возвращают двойные значения. Обычный литерал с плавающей запятой, например, когда вы пишете 3.14 в своей программе, имеет тип double. Не плавают.
На типичных современных компьютерах удвоения могут выполняться так же быстро, как и числа с плавающей запятой, или даже быстрее, поэтому производительность обычно не является важным фактором даже для больших вычислений. (И это должны быть большие вычисления, иначе производительность даже не должна приходить вам в голову. Мой новый настольный компьютер i7 может сделать шесть миллиардов умножений удвоений за одну секунду.)
На этот вопрос невозможно ответить, так как у вопроса нет контекста. Вот несколько вещей, которые могут повлиять на выбор:
Реализация компилятором чисел с плавающей запятой, чисел двойной точности и длинных чисел двойной точности. Стандарт C ++ гласит:
Существует три типа с плавающей запятой: float, double и long double. Тип double обеспечивает как минимум такую же точность, как float, а тип long double обеспечивает как минимум такую же точность, как и double.
Итак, все три могут иметь одинаковый размер в памяти.
Наличие 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.
Используйте ту точность, которая требуется для достижения соответствующих результатов . Если затем вы обнаружите, что ваш код работает не так хорошо, как хотелось бы (вы правильно использовали профилирование?), Взгляните на:
Я думаю, независимо от различий (которые, как все отмечают, с плавающей запятой занимают меньше места и в целом быстрее) ... кто-нибудь когда-либо сталкивался с проблемами производительности при использовании double? Я говорю: используйте double ... и если позже вы решите: "Вау, это действительно медленно" ... найдите узкое место в производительности (что, вероятно, не тот факт, что вы использовали double). ЗАТЕМ, если он все еще слишком медленный для вас, посмотрите, где вы можете пожертвовать точностью и использовать float.
Основное различие между float и double - точность. В Википедии есть дополнительная информация об одинарной точности (с плавающей запятой) и двойной точности .
Это сильно зависит от процессора, наиболее очевидный компромисс между точностью и памятью. С ГБ ОЗУ память не представляет особой проблемы, поэтому обычно лучше использовать double
s.
Что касается производительности, то она сильно зависит от процессора. float
s обычно дает лучшую производительность, чем double
s на 32-битной машине. На 64-битной double
версии s иногда быстрее, так как это (обычно) собственный размер. Тем не менее, гораздо больше, чем ваш выбор типов данных, будет иметь значение, сможете ли вы воспользоваться инструкциями SIMD на своем процессоре.
double имеет более высокую точность, тогда как числа с плавающей запятой занимают меньше памяти и работают быстрее. В общем, вы должны использовать float, если у вас нет случая, когда он недостаточно точен.