Используя FloatMath или Math и бросок?

В последнем обновлении Android API элемент FloatMath помечен следующим предупреждением:

В старых версиях Android использование android.util.FloatMath рекомендовалось из соображений производительности при работе с числами с плавающей запятой. Однако на современном оборудовании удвоения выполняются так же быстро, как и float (хотя они занимают больше памяти), а в последних версиях Android FloatMath на самом деле медленнее, чем использование java.lang.Math, из-за того, как JIT оптимизирует java.lang.Math. . Поэтому вам следует использовать Math вместо FloatMath, если вы ориентируетесь только на Froyo и выше.

Также упоминается здесь, что double и float равны по скорости на новейшем оборудовании.

Я использую некоторую тригонометрическую математику в приложении, над которым сейчас работаю (нацелено на Froyo и выше), но высокая точность не требуется, поэтому до сих пор я использовал числа с плавающей запятой и FloatMath, и нет никакой необходимости переключаться на удвоения.
Однако рекомендация "использовать Math вместо FloatMath" не говорит, какой из них следует использовать, если желаемым результатом является число с плавающей запятой.

Итак, короче; какой из них предпочтительнее?

float foo = FloatMath.sin(bar);

or

float foo = (float) Math.sin(bar);

Кстати, у меня есть только Froyo-устройство, поэтому я не могу провести надлежащий бенчмаркинг самостоятельно.

На уровне API 22 класс FloatMath объявлен устаревшим в пользу обычного класса Math.


person Jave    schedule 28.02.2013    source источник
comment
Я думаю, что текст, который вы цитируете, означает, что если float является желаемым результатом, вы должны использовать математику вместо floatmath и cast.   -  person aleph_null    schedule 28.02.2013
comment
Я бы воспринял любое заявление об относительной производительности int/float/double с очень большой долей скептицизма. float может быть немного быстрее просто из-за меньшего объема кэш-памяти, а на iPhone 3GS float значительно быстрее, так как он может использовать модуль NEON вместо более медленного модуля VFP (модуль NEON не поддерживает удваивается); это может быть специфично для iDevice. Кроме того, автоматическая векторизация JIT автоматически принесет float больше преимуществ, чем double, просто потому, что она может поместить больше из них в каждый векторный регистр.   -  person tc.    schedule 29.03.2013
comment
Может ли быть так, что на последних устройствах Android все числа с плавающей запятой хранятся как двойники?!   -  person Philip Guin    schedule 09.12.2013
comment
Подождите, так до API 22, исключая, FloatMath был лучше, а теперь Math лучше? Если да, то не лучше ли было бы использовать лучшее решение, основанное на API?   -  person android developer    schedule 19.08.2015


Ответы (4)


Как видно из приведенных ниже результатов, использование java.lang.Math для чисел с плавающей запятой быстрее, чем для двойных, и быстрее, чем FloatMath. Кроме того, FloatMath не имеет .exp() или .pow() до уровня API 17.

На Samsung GT_i9295 (4.2.2), 2^24 цикла

Math.exp(D)      Total:     7405 ms,     Per Op: 0.0004414 ms
(F)Math.exp(F)   Total:     5153 ms,     Per Op: 0.0003071 ms
FloatMath.exp(F) Total:     8533 ms,     Per Op: 0.0005086 ms

Нет данных для Math.sin на Samsung, потому что он случайным образом решил игнорировать Log.d() >:(

На HTC Hero_HT99VL (2.3.7), 2^12 циклов

Math.sin(D)      Total:       42 ms,     Per Op: 0.0102539 ms
(F)Math.sin(F)   Total:       33 ms,     Per Op: 0.0080566 ms
FloatMath.sin(F) Total:       38 ms,     Per Op: 0.0092773 ms

Math.exp(D)      Total:       56 ms,     Per Op: 0.0136719 ms
(F)Math.exp(F)   Total:       47 ms,     Per Op: 0.0114746 ms

FloatMath.exp(), .pos() и .hypot() требуют уровня API 17.

person A Timiney    schedule 04.09.2013

В документах для FloatMath говорится:

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

а ваша цитата говорит:

использование android.util.FloatMath было рекомендовано из соображений производительности при работе с числами с плавающей запятой

Предположительно преимущество FloatMath всегда было специально для тех случаев, когда вам нужен float, но теперь это преимущество было сведено на нет.

Так что используйте:

float foo = (float) Math.sin(bar);

Также учтите, что если производительность настолько критична, что вам нужно об этом беспокоиться, возможно, переход на double в конце концов оправдан (чтобы не нести затраты на преобразование).

person kabuko    schedule 28.02.2013
comment
Если в настоящее время нет разницы в работе с числами типа double или float, все равно могут возникнуть накладные расходы на преобразование типов float в double и наоборот. Таким образом, использование Math повлечет за собой преобразование из одного типа в другой, а FloatMath будет работать непосредственно с числами с плавающей запятой. Так почему лучше использовать математику? - person Egor; 28.02.2013
comment
некоторые из математических методов принимают двойные значения в качестве аргументов, поэтому также происходит некоторое неявное приведение типов. - person Jave; 28.02.2013
comment
@ Егор Я не знаю подробностей, почему использование Math лучше, чем то, что было упомянуто, все, что я говорю, это то, что документы и предупреждение о ворсе, похоже, подразумевают, что вы должны использовать Math вместо FloatMath даже с учетом стоимости преобразования . Кроме того, рекомендуется просто использовать double вместо float. если пространство не является проблемой. - person kabuko; 28.02.2013


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

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

Если для вашего приложения важно, чтобы значения были с плавающей запятой (например, из-за потребления памяти), вы должны продолжать использовать FloatMath, потому что float foo = (float) Math.sin(bar); станет раздражать, если вы будете его часто использовать.

person Cephalopod    schedule 28.02.2013