Подтвердить что ты не робот

Использование FloatMath или Math и литье?

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

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

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

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

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

float foo = FloatMath.sin(bar);

или

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

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

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

4b9b3361

Ответ 1

Как видно из приведенных ниже результатов, использование java.lang.Math быстрее для float, чем для парных, и быстрее, чем 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

Ответ 2

docs для FloatMath говорят:

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

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

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

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

Поэтому используйте:

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

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

Ответ 3

Я недавно изучал эту же проблему и нашел этот отчет об ошибке в этой проблеме. Функции Math превосходят числа FloatMath на порядок, как показано в приведенной ниже цитате:

Используя DDMS, я профилировал этот код. Каждая из нижеприведенных функций была вызвана через 100x.

       Name                 | Cpu Time / Call
----------------------------------------------
java/lang/Math.sin (D)D     | 0.005
java/lang/Math.cos (D)D     | 0.007
java/lang/Math.sqrt (D)D    | 0.004
android/util/FloatMath.sin  | 0.017
android/util/FloatMath.cos  | 0.017
android/util/FloatMath.sqrt | 0.016

Если вы следуете изменениям документации в дереве AOSP, вы увидите здесь, что Math функции предпочтительнее FloatMath для версий андроида с JIT, что в основном есть у Froyo (2.2) и выше.

Ответ 4

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

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

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