37

In the latest update of the Android API the FloatMath is marked with the following lint-warning:

In older versions of Android, using android.util.FloatMath was recommended for performance reasons when operating on floats. However, on modern hardware doubles are just as fast as float (though they take more memory), and in recent versions of Android, FloatMath is actually slower than using java.lang.Math due to the way the JIT optimizes java.lang.Math. Therefore, you should use Math instead of FloatMath if you are only targeting Froyo and above.

It is also mentioned here that double and float are equal in speed on recent hardware.

I am using some trigonometric math in an application I am currently working on (targeted Froyo and above), but high precision is not needed, so I have been using floats and FloatMath so far, and there is no need whatsoever to switch to doubles.
However, the "use Math over FloatMath"-recommendation does not say which one to use if float is the desired result.

So, in short; which one is preferable?

float foo = FloatMath.sin(bar);

or

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

On a side note, I only have a Froyo-device, so I can't really do any proper benchmarking on my own.

As of API level 22 the FloatMath-class has been deprecated in favor of the regular Math-class.

Jave
  • 31,598
  • 14
  • 77
  • 90
  • I think that text you quoted means that if float is the desired result, you should use math instead of floatmath and cast. – aleph_null Feb 28 '13 at 19:17
  • 2
    I'd take any claim of the relative performance of `int`/`float`/`double` with a very large grain of salt. `float` can be slightly faster simply due to the smaller cache footprint, and on the iPhone 3GS, `float` is *significantly* faster since it can use the NEON unit instead of the slower VFP unit (the NEON unit does not support doubles); this may be iDevice-specific. Additionally, an auto-vectorizing JIT will automatically benefit `float` more than `double` simply because it can fit more of them in each vector register. – tc. Mar 28 '13 at 20:23
  • Could it be that floats are all stored as doubles on the latest Android devices?! – Philip Guin Dec 09 '13 at 04:16
  • 1
    `FloatMath` - [*"**This class was deprecated in API level 22.** Use `Math` instead."*](http://developer.android.com/reference/android/util/FloatMath.html). – Pang Jun 04 '15 at 05:02
  • Wait, so up to API 22 , excluding, FloatMath was better, and now Math is better? If so, wouldn't it make more sense to make it use the better solution, based on the API ? – android developer Aug 19 '15 at 08:35

4 Answers4

14

As you can see from the results below, using java.lang.Math is faster for floats than for doubles, and faster than FloatMath. Furthermore, FloatMath has no .exp() or .pow() prior to API level 17.

On a Samsung GT_i9295 (4.2.2), 2^24 cycles

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

No data for Math.sin on the samsung because it has randomly decided to ignore Log.d() >:(

On a HTC Hero_HT99VL (2.3.7), 2^12 cycles

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() and .hypot() require API level 17

A Timiney
  • 156
  • 1
  • 3
5

The docs for FloatMath say:

Math routines similar to those found in Math. Performs computations on float values directly without incurring the overhead of conversions to and from double.

and your quote says:

using android.util.FloatMath was recommended for performance reasons when operating on floats

Presumably the benefit of FloatMath was always specifically for when you want a float, but this benefit has now been negated.

So use:

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

Also consider that if performance is so critical that you need to worry about this, maybe the switch to double is warranted after all (as not to incur the cost of conversion).

kabuko
  • 36,028
  • 10
  • 80
  • 93
  • If there is no difference in operating doubles or floats nowadays, there can still be overhead of converting floats to doubles and vice versa. So using Math will incur converting from one type to another, and FloatMath will operate directly on floats. So why using Math is better? – Egor Feb 28 '13 at 19:30
  • some of the Math-methods take doubles as arguments, so there is also some implicit casting taking place. – Jave Feb 28 '13 at 19:31
  • 3
    @Egor I don't know the details of exactly why using `Math` is better beyond what's been mentioned, all I'm saying is that the docs and lint warning seem to imply that you should use `Math` over `FloatMath` even when considering the cost of conversion. Also, just using `double` instead of `float` in general is [recommended](http://developer.android.com/training/articles/perf-tips.html#AvoidFloat) unless space is an issue. – kabuko Feb 28 '13 at 19:38
2

I was just looking into the same issue recently and found this bug report on the issue. The Math functions outperform the FloatMath ones by an order of magnitude, as shown on the quote below:

Using DDMS, I profiled the code in question. Each of the functions below were called over 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

If you follow the documentation changes in the AOSP tree you'll see here that Math functions are preferred to FloatMath on versions of android with a JIT, which is basically anything from Froyo (2.2) and up.

ebarrenechea
  • 3,775
  • 1
  • 31
  • 37
-1

If performance is that important, then you probably don't want to waste the time to cast to and from doubles every time you calculate something.

As I understand it, on older hardware floats were faster than doubles, thus you needed a Math library for floats. Now, "on modern hardware doubles are just as fast as float", thus you should use the default Math with doubles.

If it is important for your application that the values are floats (e.g., because of memory consumption), you should continue using FloatMath, because float foo = (float) Math.sin(bar); will become annoying if you use it a lot.

Cephalopod
  • 14,632
  • 7
  • 51
  • 70