Вопрос по c++, types – Должен ли я использовать double или float?

74

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

Ваш Ответ

11   ответов
27

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

  1. Compiler implementation of floats, doubles and long doubles. The C++ standard states:

    There are three floating point types: float, double, and long double. The type double provides at least as much precision as float, and the type long double provides at least as much precision as double.

    So, all three can be the same size in memory.

  2. Presence of an FPU. Not all CPUs have FPUs and sometimes the floating point types are emulated and sometimes the floating point types are just not supported.

  3. FPU Architecture. The IA32's FPU is 80bit internally - 32 bit and 64 bit floats are expanded to 80bit on load and reduced on store. There's also SIMD which can do four 32bit floats or two 64bit floats in parallel. Use of SIMD is not defined in the standard so it would require a compiler that does more complex analysis to determine if SIMD can be used, or requires the use of special functions (libraries or intrinsics). The upshot of the 80bit internal format is that you can get slightly different results depending on how often the data is saved to RAM (thus, losing precision). For this reason, compilers don't optimise floating point code particularly well.

  4. Memory bandwidth. If a double requires more storage than a float, then it will take longer to read the data. That's the naive answer. On a modern IA32, it all depends on where the data is coming from. If it's in L1 cache, the load is negligible provided the data comes from a single cache line. If it spans more than one cache line there's a small overhead. If it's from L2, it takes a while longer, if it's in RAM then it's longer still and finally, if it's on disk it's a huge time. So the choice of float or double is less important than the way the data is used. If you want to do a small calculation on lots of sequential data, a small data type is preferable. Doing a lot of computation on a small data set would allow you to use bigger data types with any significant effect. If you're accessing the data very randomly, then the choice of data size is unimportant - data is loaded in pages / cache lines. So even if you only want a byte from RAM, you could get 32 bytes transferred (this is very dependant on the architecture of the system). On top of all of this, the CPU/FPU could be super-scalar (aka pipelined). So, even though a load may take several cycles, the CPU/FPU could be busy doing something else (a multiply for instance) that hides the load time to a degree.

  5. The standard does not enforce any particular format for floating point values.

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

4

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

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

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

3

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

2

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

91

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

Короче, хотяdouble позволяетhigher precision в своем представлении, для определенных расчетов он будет производитьlarger errors, & Quot; Право & quot; Выбор есть:use as much precision as you need but not more а такжеchoose the right algorithm.

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

Дополнительные примечания: если вы абсолютно не представляете, как выглядят данные (или просто не имеете никакого представления о математике в ссылках), просто используйтеdouble - в большинстве случаев это безопаснее.
@ Грег Роджерс: компиляторы не настолько умны в данный момент. Если вы не пишете необработанную сборку, она не имеет большого значения. И да, это может измениться по мере развития компилятора.
Эта статья не короткая.
Да. Благодаря тому, что современные процессоры предварительно выбирают все большие и большие куски памяти, параллельные вычислительные блоки и конвейерные архитектуры, проблема скорости на самом деле не является проблемой. Если вы имеете дело с огромным количеством цифр, то, возможно,size Разница между 4-байтовым плавающим и 8-байтовым двойнымmight сделать разницу в памяти.
Ну, SSE (или любой другой блок с плавающей запятой) сможет обрабатывать вдвое больше флопов с одинарной точностью по сравнению с двойной точностью. Если вы используете только x87 (или любую скалярную) с плавающей точкой, то это, вероятно, не имеет значения.
1

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

6

Лично я иду вдвоем, пока не увижу узкие места. Тогда я подумываю перейти на плавание или оптимизировать какую-то другую часть.

13

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

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

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

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

+1 для смешивания может вызвать проблемы
Обратите внимание, что 4/8 байтов для float / double даже не гарантированы, это будет зависеть от платформы. Это может быть даже тот же тип ...
1

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

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

29

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

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

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

0

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

На типичных современных компьютерах double так же быстр, как и float.

Похожие вопросы