Когда использовать поплавок - PullRequest
38 голосов
/ 02 января 2009

Несколько лет назад я усердно изучал проблемы точности с поплавками, поэтому я перестал их использовать. Тем не менее, я все еще сталкиваюсь с кодом, используя float, и это заставляет меня съеживаться, потому что я знаю, что некоторые вычисления будут неточными.

Итак, когда уместно использовать поплавок?

EDIT: Как информация, я не думаю, что я сталкивался с программой, где точность числа не важна. Но мне было бы интересно услышать примеры.

Ответы [ 7 ]

53 голосов
/ 02 января 2009

Краткий ответ: Вы должны использовать float только тогда, когда точно знаете, что делаете и почему.

Длинный ответ: с плавающей точкой (в отличие от doubles ), насколько я знаю, больше не используются вне 3D API Плавающие и двойные имеют одинаковые характеристики производительности на современных процессорах, двойные несколько больше, и все. Если сомневаетесь, просто используйте double.

О, да, и, конечно, используйте десятичный для финансовых расчетов.

11 голосов
/ 02 января 2009

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

Что касается того, когда использовать поплавки - они часто используются, когда точность менее важна, чем сохранение памяти. Например, простые симуляции частиц в видеоиграх.

8 голосов
/ 03 января 2009

Во-первых, никогда не используйте числа с плавающей запятой или двойные числа, если вы хотите точно представлять десятичные значения - используйте целочисленные типы (int, long и т. Д.) Или десятичные (это просто целочисленный тип с коэффициентом масштабирования). Числа с плавающей запятой и числа с двойными числами преобразуются внутренне в экспоненциальное представление в базе 2, а числа, представленные точно в экспоненциальном представлении в базе 10, в общем случае не могут быть представлены точно. (Например, число 10 представлено только приблизительно с плавающей или двойной).

Во-вторых, с точки зрения точности это зависит от того, что вам нужно. Я не согласен с вашим мнением, что никогда не бывает расчетов, где точность не имеет значения. Обычно у вас есть конкретная потребность, чтобы ваш конечный результат был точным, 3 цифры. Не имеет смысла искать максимально возможную точность, если ваши входные данные имеют только ограниченную точность - скажем, вы весите около 5 г муки, а ваша шкала имеет точность только до 0,5 г. Тем не менее, промежуточные вычисления обычно выигрывают от более высокой точности, но что-то более важное, чем высокая точность, если довольно часто скорость.

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

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

Насколько мне известно, обработка с плавающей запятой поддерживается аппаратно для двойных чисел, но не для чисел с плавающей запятой, поэтому при использовании чисел с плавающей запятой происходит преобразование в двойную. Однако некоторые подпрограммы будут останавливаться раньше при итеративном вычислении значения при передаче значения с плавающей запятой, поскольку это подразумевает, что вам нужна точность порядка 8 цифр против около 16 для двойных чисел.

7 голосов
/ 02 января 2009

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

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

5 голосов
/ 20 февраля 2009

На самом деле есть одна вещь, где все еще распространено использование float aka «одинарная точность» с 32 битами: графические приложения и печать.

Другая причина - графические карты с графическими процессорами. Чем меньше тип данных, тем быстрее операция, потому что должно быть транспортировано меньше битов. Целочисленные типы данных имеют проблемы с изображениями с высоким динамическим диапазоном: глаз способен функционировать в диапазоне яркости 1: 10 ^ 13 и различает ок. 4000 уровней. Таким образом, хотя целочисленные типы данных могут хранить количество уровней, они не в состоянии сохранить яркость фона, в то время как с плавающей точкой проблем с этим нет. На самом деле IEEE 754R допускает новое «половинное» плавание с 16 битами и 10 битами мантисса, которая теряет некоторую точность, но позволила бы еще большую скорость. OpenGL и DirectX, например использовать плавает широко. Глаз очень прощающий с артефактами, поэтому проблем нет.

Все остальные мультимедийные объекты, основанные на графике, наследуют числа с плавающей запятой в качестве удобной меры. Мантисса имеет 24 бита, что позволяет 2 ^ 24 = 16,7 миллионов последовательных шагов. Если у вас есть принтер с разрешением 2000 точек на дюйм, вы по-прежнему можете печатать 213x213 м листы. Более чем достаточно точности.

5 голосов
/ 03 января 2009

Самая распространенная причина, по которой я могу придумать, - это сэкономить место. Не то чтобы об этом часто стоило беспокоиться, но в некоторых случаях это имеет значение. Число с плавающей запятой занимает вдвое больше памяти, чем двойное, поэтому вы можете получить вдвое больше в одном и том же пространстве. Например, у меня был массив чисел, который был слишком велик, чтобы помещаться в ОЗУ в виде двойных чисел, но помещался в плавающий массив.

3 голосов
/ 03 января 2009

Используйте float для производительности и размера . Если вы можете управлять потерей точности.

Несмотря на то, что современному процессору требуется одинаковое количество времени для обработки операций одинарной и двойной точности, иногда вы можете получить удвоенную пропускную способность, если используете операции с плавающей запятой с SIMD (MMX / SSE / и т. Д.). на x86) инструкции.

Регистры SSE имеют ширину 128 битов и могут содержать 4 числа с плавающей запятой или 2 двойных числа . Таким образом, при правильном использовании вы можете выполнять в два раза больше операций с числами с плавающей запятой по сравнению с double.

Уменьшение размера (4 байта вместо 8) становится важным при работе с очень большими наборами данных (а уменьшение размера обычно также повышает производительность за счет кэширования и т. Д.)

...