Можно ли помочь мне разъяснить использования примитива плавающего в Java?
Мое понимание - то, что преобразование значения плавающего для удвоения и наоборот может быть проблематичным. Я читал (скорее давным-давно и не уверенный, что это фактическое верный больше с новым JVMs), что выполнение плавания намного хуже, чем double's. И конечно плавания имеют меньше точности, чем дважды.
Я также помню, что, когда я работал с AWT и Swing, у меня были некоторые проблемы с использованием плавания или дважды (как использование Point2D.Float или Point2D.Double).
Так, я вижу только 2 преимущества плавания по дважды:
Требуется только 4 байта, в то время как дважды нуждается в 8 байтах
Модель памяти Java (JMM) гарантирует, что операция присвоения является атомарной с переменными плавающими, в то время как это не является атомарным с double's.
Есть ли какие-либо другие случаи, где плавание лучше затем дважды? Вы используете плавание в своих приложениях?
Причина включения типа float в некоторой степени историческая: он представляет собой стандартное представление с плавающей запятой IEEE с тех времен, когда было сокращено 4 байта. размер числа с плавающей запятой в обмен на крайне низкую точность был компромиссом, на который стоило пойти.
В настоящее время использование float довольно ограничено. Но, например, наличие типа данных может упростить написание кода, который требует взаимодействия со старыми системами, которые действительно используют float.
Что касается производительности, я думаю, что float и double по сути идентичны , за исключением производительности делений . Как правило, что бы вы ни использовали, процессор преобразует его в свой внутренний формат, выполняет вычисления, а затем снова преобразует их обратно, и фактическое вычисление фактически занимает фиксированное время. В случае деления, по крайней мере на процессорах Intel, насколько я помню, время, затрачиваемое на деление, обычно составляет один тактовый цикл на 2 бита точности, поэтому, используете ли вы float или double, имеет значение.
Если у вас действительно нет веских причин использовать его в новом коде, я бы вообще избегал float.
Это правда, что в некоторых случаях операции типа double могут выполняться быстрее, чем операции с плавающей запятой. Однако для этого необходимо, чтобы все умещалось в кэше L1. С помощью float вы можете иметь вдвое больше в строке кэша. Это может заставить некоторые программы работать почти в два раза быстрее.
Инструкции SSE также могут работать параллельно с 4 числами с плавающей запятой вместо 2, но я сомневаюсь, что JIT действительно их использует. Хотя я могу ошибаться.
Думаю, вы справились с этим, когда упомянули о хранилище, когда размер с плавающей запятой составляет половину.
Использование чисел с плавающей запятой может показать улучшенную производительность по сравнению с числами с плавающей запятой для приложений, обрабатывающих большие массивы чисел с плавающей запятой, так что пропускная способность памяти является ограничивающим фактором. Переключившись на float []
с double []
и уменьшив вдвое размер данных, вы фактически удвоите пропускную способность, потому что за заданное время можно получить вдвое больше значений. Хотя у процессора есть немного больше работы для преобразования числа с плавающей запятой в двойное, это происходит параллельно с выборкой из памяти, причем выборка занимает больше времени.
Для некоторых приложений потеря точности может стоить торговли ради увеличения производительности. Затем снова...: -)
Итак, да, преимущества чисел с плавающей запятой:
Способы уменьшить это при использовании двойников:
Кто-то еще упомянул, что это похоже на аргумент short vs int, но это не так. Все целочисленные типы (включая логические), кроме long, хранятся как 4-байтовые целые числа в модели памяти Java, если они не хранятся в массиве.
Эти две причины, которые вы только что привели, огромны.
Если у вас есть трехмерный объем размером 1k на 1k на 64, а затем у вас есть много временных точек для этих данных, а затем вы хотите снять фильм с проекциями максимальной интенсивности, тот факт, что float составляет половину размера double, может быть разница между быстрым завершением и отбивкой из-за нехватки памяти.
Атомарность также огромна с точки зрения многопоточности.
Всегда будет компромисс между скоростью / производительностью и точностью. Если у вас есть число меньше 2 ^ 31 и целое число, то целое число всегда является лучшим представлением этого числа, чем число с плавающей запятой, просто из-за потери точности. Вам нужно будет оценить свои потребности и использовать подходящие типы для ваших проблем.