Поскольку, что цель Java имеет типом примитива плавающим?

Можно ли помочь мне разъяснить использования примитива плавающего в Java?

Мое понимание - то, что преобразование значения плавающего для удвоения и наоборот может быть проблематичным. Я читал (скорее давным-давно и не уверенный, что это фактическое верный больше с новым JVMs), что выполнение плавания намного хуже, чем double's. И конечно плавания имеют меньше точности, чем дважды.

Я также помню, что, когда я работал с AWT и Swing, у меня были некоторые проблемы с использованием плавания или дважды (как использование Point2D.Float или Point2D.Double).

Так, я вижу только 2 преимущества плавания по дважды:

  1. Требуется только 4 байта, в то время как дважды нуждается в 8 байтах

  2. Модель памяти Java (JMM) гарантирует, что операция присвоения является атомарной с переменными плавающими, в то время как это не является атомарным с double's.

Есть ли какие-либо другие случаи, где плавание лучше затем дважды? Вы используете плавание в своих приложениях?

22
задан 6 revs, 4 users 83% 11 May 2012 в 15:02
поделиться

5 ответов

Причина включения типа float в некоторой степени историческая: он представляет собой стандартное представление с плавающей запятой IEEE с тех времен, когда было сокращено 4 байта. размер числа с плавающей запятой в обмен на крайне низкую точность был компромиссом, на который стоило пойти.

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

Что касается производительности, я думаю, что float и double по сути идентичны , за исключением производительности делений . Как правило, что бы вы ни использовали, процессор преобразует его в свой внутренний формат, выполняет вычисления, а затем снова преобразует их обратно, и фактическое вычисление фактически занимает фиксированное время. В случае деления, по крайней мере на процессорах Intel, насколько я помню, время, затрачиваемое на деление, обычно составляет один тактовый цикл на 2 бита точности, поэтому, используете ли вы float или double, имеет значение.

Если у вас действительно нет веских причин использовать его в новом коде, я бы вообще избегал float.

16
ответ дан 29 November 2019 в 05:13
поделиться

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

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

2
ответ дан 29 November 2019 в 05:13
поделиться

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

Использование чисел с плавающей запятой может показать улучшенную производительность по сравнению с числами с плавающей запятой для приложений, обрабатывающих большие массивы чисел с плавающей запятой, так что пропускная способность памяти является ограничивающим фактором. Переключившись на float [] с double [] и уменьшив вдвое размер данных, вы фактически удвоите пропускную способность, потому что за заданное время можно получить вдвое больше значений. Хотя у процессора есть немного больше работы для преобразования числа с плавающей запятой в двойное, это происходит параллельно с выборкой из памяти, причем выборка занимает больше времени.

Для некоторых приложений потеря точности может стоить торговли ради увеличения производительности. Затем снова...: -)

3
ответ дан 29 November 2019 в 05:13
поделиться

Итак, да, преимущества чисел с плавающей запятой:

  1. Требуется всего 4 байта
  2. Атомарное присваивание
  3. Арифметика должна быть быстрее, особенно на 32-битных архитектурах, поскольку существуют определенные байтовые коды с плавающей запятой.

Способы уменьшить это при использовании двойников:

  1. Купите больше оперативной памяти, это действительно дешево.
  2. Используйте изменчивые двойники, если вам нужно атомарное присваивание.
  3. Проведите тесты, проверьте производительность каждого из них, если один действительно быстрее, вы мало что можете с этим поделать.

Кто-то еще упомянул, что это похоже на аргумент short vs int, но это не так. Все целочисленные типы (включая логические), кроме long, хранятся как 4-байтовые целые числа в модели памяти Java, если они не хранятся в массиве.

3
ответ дан 29 November 2019 в 05:13
поделиться

Эти две причины, которые вы только что привели, огромны.

Если у вас есть трехмерный объем размером 1k на 1k на 64, а затем у вас есть много временных точек для этих данных, а затем вы хотите снять фильм с проекциями максимальной интенсивности, тот факт, что float составляет половину размера double, может быть разница между быстрым завершением и отбивкой из-за нехватки памяти.

Атомарность также огромна с точки зрения многопоточности.

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

8
ответ дан 29 November 2019 в 05:13
поделиться
Другие вопросы по тегам:

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