views:

500

answers:

5

The default floating point type in Java is the double. If you hard code a constant like 2.5 into your program, Java makes it a double automatically. When you do an operation on floats or ints that could potentially benefit from more precision, the type is 'promoted' to a double.

But in the Android API, everything seems to be a float from sound volumes to rectangle coordinates. There's a structure called RectF used in most drawing; the F is for float. It's really a pain for programmers who are casting promoted doubles back to (float) pretty often. Don't we all agree that Java code is messy and verbose enough as it is?

Usually math coprocessors and accelerators prefer double in Java because it corresponds to one of the internal types. Is there something about Android's Dalvik VM that prefers floats for some reason? Or are all the floats just a result of perversion in API design?

+3  A: 
Roman Nurik
+2  A: 

Weird. Designing for Performance in the guide seems to say "....The common practice on desktop systems is to use floating point freely......so all operations on "float" and "double" are performed in software...." at http://developer.android.com/guide/practices/design/performance.html#avoidfloat

This may make some sense: "....Instructions aren't gratuitously limited to a particular type. For example, instructions that move 32-bit register values without interpretation don't have to specify whether they are moving ints or floats....." at http://www.netmite.com/android/mydroid/dalvik/docs/dalvik-bytecode.html

frissony
i've rewritten most of "designing for performance" for froyo. modern devices like Droid and the Nexus One have floating point hardware, which means that division of floats/doubles is actually faster than division of ints/longs (because there's still no hardware integer divide).
Elliott Hughes
The note in the Dalvik bytecode doc is more with regard to design of the instruction set and code verification. The idea is that, internally, whether I load a register with an "integer constant" 0 or a "float constant" 0 is irrelevant; it's just a 32-bit value. Not really related to float vs. double or performance.
fadden
+5  A: 

Depending on the CPU there will be no Floating Point Unit (FPU). So it has to emulate the FPU in Software. this is faster for a Float than for a Double. Or if the Device has a FPU it will be probably also be faster with Floats.

nuriaion
This is the closest to the correct reason, from the devs. It's not really memory. ARMs have no FPU, or ones that do have a 32-bit FPU. Emulation of 64-bit doubles is slow.
Sean Owen
the other answer from "fadden" (one of the guys who wrote the VM) is the best answer.
Elliott Hughes
Jesse Wilson
+2  A: 

I think Roman is correct, that the reason is likely mostly intended to reduce memory usage. Consider that when ultimate precision isn't important you will halve the memory needed for numeric variables.

Remember though that it isn't necessary to use casting. Simply append an F to your literal (so 2.5 becomes 2.5f). I don't know if the compiler is smart enough to do the following substitution for you, but if not, this will make your code slightly more efficient as well.

Consider

float x = (float) 2.5;

and

float x = 2.5f;

In the first case, at run time, the program stores a double, then carries out a cast operation, before storing the resulting float value. In the second case the compiler will recognize the value as a float, so at run time you avoid both the storing of a double (however temporarily that might be) and also avoiding the cast operation (since it is already stored as a float).

Jimbugs
+8  A: 

On devices without an FPU, the single-precision floating point ops are much faster than the double-precision equivalents. Because of this, the Android framework provides a FloatMath class that replicates some java.lang.Math functions, but with float arguments instead of double.

On recent Android devices with an FPU, the time required for single- and double-precision operations is about the same, and is significantly faster than the software implementation. (The "Designing for Performance" page was written for the G1, and needs to be updated to reflect various changes.)

Incidentally, writing "2.5f" or "(float) 2.5" doesn't matter. Either way, javac knows you want a single-precision float constant, and that's what it generates. You can verify this by writing a sample program and examining the bytecode generated.

fadden