2010-03-19 10 views
16

El tipo de punto flotante predeterminado en Java es el doble. Si codifica una constante como 2.5 en su programa, Java la duplica automáticamente. Cuando realiza una operación en flotadores o ints que podría beneficiarse de una mayor precisión, el tipo se "promociona" a un doble.¿Por qué hay tantos flotantes en la API de Android?

Pero en la API de Android, todo parece flotar desde los volúmenes de sonido a las coordenadas del rectángulo. Hay una estructura llamada RectF utilizada en la mayoría de los dibujos; la F es para flotar. Realmente es un dolor para los programadores que están lanzando dobles promocionados de vuelta a (float) con bastante frecuencia. ¿No todos estamos de acuerdo en que el código de Java es lo suficientemente complicado y prolijo como es?

Por lo general, los aceleradores y los coprocesadores matemáticos prefieren el doble en Java porque corresponde a uno de los tipos internos. ¿Hay algo acerca de Dalvik VM de Android que prefiera carrozas por alguna razón? ¿O todas las carrozas son solo el resultado de una perversión en el diseño de API?

+0

¿Cuándo se promocionan las carrozas o ints a dobles cuando no había ningún doble para comenzar? – Karu

Respuesta

8

Dependiendo de la CPU no habrá unidad de punto flotante (FPU). Entonces tiene que emular la FPU en el Software. esto es más rápido para un Float que para un Double. O si el dispositivo tiene una FPU, probablemente también sea más rápido con Floats.

+1

Esto es lo más cercano a la razón correcta, de los desarrolladores. No es realmente memoria. Los ARM no tienen FPU, o los que sí tienen una FPU de 32 bits. La emulación de dobles de 64 bits es lenta. –

+7

la otra respuesta de "fadden" (uno de los tipos que escribió el VM) es la mejor respuesta. –

+0

Corrección: en dispositivos modernos, los flotadores y los dobles son equivalentes. –

7

Para métricas que no necesitan demasiados dígitos significativos (como desplazamientos de pantalla), sería ineficiente en la memoria usar double s en lugar de float s. Maximizar la eficiencia en lo que respecta al consumo de memoria es de vital importancia en los dispositivos móviles, donde casi todos los recursos son escasos. Y, cuando se trata de objetos como Rect s — que podrían asignarse potencialmente por miles —, es claramente crucial reducir el exceso de bits.

estoy seguro de que hay otras razones también :-)

3

extraño. El diseño para el rendimiento en la guía parece decir ".... La práctica común en los sistemas de escritorio es usar punto flotante libremente ...... así que todas las operaciones en" flotante "y" doble "se realizan en el software ... . "en http://developer.android.com/guide/practices/design/performance.html#avoidfloat

Esto puede tener algún sentido: " .... Las instrucciones no se limitan a un tipo en particular. Por ejemplo, las instrucciones que mueven valores de registro de 32 bits sin interpretación no tienen que especificar si se están moviendo hacia adentro o flotadores ..... " en http://www.netmite.com/android/mydroid/dalvik/docs/dalvik-bytecode.html

+1

he reescrito la mayor parte del "diseño para el rendimiento" de froyo. dispositivos modernos como Droid y Nexus One tienen hardware de punto flotante, lo que significa que la división de flotantes/dobles es en realidad más rápida que la división de ints/longs (porque todavía no hay divisiones enteras de hardware). –

+1

La nota en el documento de bytecode Dalvik es más con respecto al diseño del conjunto de instrucciones y la verificación de código. La idea es que, internamente, si cargo un registro con una "constante entera" 0 o una "constante flotante" 0 es irrelevante; es solo un valor de 32 bits. No está realmente relacionado con float vs. double o performance. – fadden

1

Creo que Roman tiene razón, que la razón probablemente sea principalmente para reducir el uso de memoria. Considere que cuando la precisión final no es importante, reducirá a la mitad la memoria necesaria para las variables numéricas.

Recuerde, sin embargo, que no es necesario utilizar el casting. Simplemente agregue una F a su literal (por lo que 2.5 se convierte en 2.5f). No sé si el compilador es lo suficientemente inteligente como para hacer la siguiente sustitución por usted, pero si no, esto hará que su código sea ligeramente más eficiente también.

Considere

float x = (float) 2.5; 

y

float x = 2.5f; 

En el primer caso, en tiempo de ejecución, el programa almacena una continuación, lleva a cabo una doble operación, fundido, antes de almacenar el valor en coma flotante resultante.En el segundo caso, el compilador reconocerá el valor como un flotante, por lo que en el tiempo de ejecución evitará tanto el almacenamiento de un doble (aunque sea temporalmente) como la operación de conversión (ya que está almacenada como flotante).

+0

¿Estás seguro? Acabo de probar, ambas versiones generan bytecode idéntico. Ver la respuesta de Fadden. – Oliv

+0

@Oliv - fadden respondió después de mí, y creo que dejé en claro que no, no estaba seguro. Considere "No sé si el compilador ..." – Jimbugs

43

En dispositivos sin una FPU, las operaciones de punto flotante de precisión simple son mucho más rápidas que las equivalencias de doble precisión. Debido a esto, Android Framework proporciona una clase FloatMath que replica algunas funciones java.lang.Math, pero con argumentos flotantes en lugar de dobles.

En dispositivos Android recientes con una FPU, el tiempo requerido para las operaciones de precisión simple y doble es aproximadamente el mismo, y es significativamente más rápido que la implementación del software. (La página "Proyectos para mejorar el rendimiento" fue escrita para el G1, y necesita ser actualizado para reflejar los diversos cambios.)

Por cierto, escribiendo "2.5f" o "(float) 2.5" no importa. De cualquier forma, javac sabe que quiere una constante de flotación de precisión simple, y eso es lo que genera. Puede verificar esto escribiendo un programa de muestra y examinando el bytecode generado.

Cuestiones relacionadas