¿Debería usar doble o flotante?

89

¿Cuáles son las ventajas y desventajas de usar uno en lugar del otro en C ++?

AraK
fuente
¿Alguien ha intentado hacer una matriz de flotantes y una matriz de dobles y ver si de hecho hay 4 bytes entre miembros en flotantes y 8 bytes entre miembros en dobles? Es posible que un compilador / computadora de 64 bits aún reserve 8 bytes por miembro para flotantes aunque no necesiten tanto.
user3015682

Respuestas:

104

Si desea conocer la respuesta verdadera, debe leer Lo que todo informático debe saber sobre la aritmética de coma flotante .

En definitiva, si bien doublepermite una mayor precisión en su representación, para ciertos cálculos produciría errores mayores . La opción "correcta" es: utilice tanta precisión como necesite, pero no más, y elija el algoritmo correcto .

Muchos compiladores hacen cálculos matemáticos de punto flotante extendidos en modo "no estricto" de todos modos (es decir, usan un tipo de punto flotante más amplio disponible en hardware, por ejemplo, 80 bits y 128 bits flotantes), esto también debe tenerse en cuenta. En la práctica, casi no se puede ver ninguna diferencia en la velocidad ; de todos modos, son nativos del hardware.

J-16 SDiZ
fuente
10
Si. Con las CPU modernas que precargan fragmentos de memoria cada vez más grandes, unidades de procesamiento numérico en paralelo y arquitecturas canalizadas, el problema de la velocidad no es realmente un problema. Si está tratando con grandes cantidades de números, entonces quizás la diferencia de tamaño entre un flotante de 4 bytes y un doble de 8 bytes podría marcar la diferencia en la huella de memoria.
lavinio
5
El pozo SSE (o cualquier unidad de coma flotante vertical) podrá procesar el doble de flops con precisión simple en comparación con precisión doble. Si está haciendo solo x87 (o cualquier punto flotante escalar), probablemente no importe.
Greg Rogers
1
@Greg Rogers: los compiladores no son tan inteligentes en este momento. A menos que esté escribiendo un ensamblaje en bruto, no tiene grandes diferencias. Y sí, esto puede cambiar a medida que evoluciona el compilador.
J-16 SDiZ
Notas adicionales: si no tiene absolutamente ninguna idea de cómo se ven los datos (o simplemente no tiene ni idea de todas las matemáticas en los enlaces), simplemente utilícelo double, es más seguro en la mayoría de los casos.
J-16 SDiZ
2
Este artículo no es corto.
jokoon
44

A menos que tenga alguna razón específica para hacer lo contrario, use double.

Quizás sorprendentemente, es doble y no flotante el tipo de punto flotante "normal" en C (y C ++). Las funciones matemáticas estándar como sin y log toman dobles como argumentos y devuelven dobles. Un literal de coma flotante normal, como cuando escribe 3.14 en su programa, tiene el tipo double. No flotar.

En las computadoras modernas típicas, los dobles pueden ser tan rápidos como los flotantes, o incluso más rápidos, por lo que el rendimiento generalmente no es un factor a considerar, incluso para cálculos grandes. (Y tendrían que ser cálculos grandes , o el rendimiento ni siquiera debería entrar en su mente. Mi nueva computadora de escritorio i7 puede hacer seis mil millones de multiplicaciones de dobles en un segundo).

Thomas Padron-McCarthy
fuente
26

Esta pregunta es imposible de responder ya que no hay contexto para la pregunta. A continuación, se muestran algunas cosas que pueden afectar la elección:

  1. Implementación del compilador de flotadores, dobles y dobles largos. El estándar C ++ establece:

    Hay tres tipos de coma flotante: float, double y long double. El tipo double proporciona al menos tanta precisión como float, y el tipo long double proporciona al menos tanta precisión como double.

    Entonces, los tres pueden tener el mismo tamaño en memoria.

  2. Presencia de una FPU. No todas las CPU tienen FPU y, a veces, los tipos de punto flotante se emulan y, a veces, los tipos de punto flotante simplemente no son compatibles.

  3. Arquitectura FPU. La FPU del IA32 es internamente de 80 bits: los flotadores de 32 y 64 bits se amplían a 80 bits con carga y se reducen en la tienda. También hay SIMD que puede hacer cuatro flotadores de 32 bits o dos flotadores de 64 bits en paralelo. El uso de SIMD no está definido en el estándar, por lo que requeriría un compilador que realice un análisis más complejo para determinar si se puede usar SIMD o si requiere el uso de funciones especiales (bibliotecas o intrínsecas). El resultado del formato interno de 80 bits es que puede obtener resultados ligeramente diferentes dependiendo de la frecuencia con la que se guardan los datos en la RAM (por lo tanto, se pierde precisión). Por esta razón, los compiladores no optimizan el código de punto flotante particularmente bien.

  4. Ancho de banda de memoria. Si un doble requiere más almacenamiento que un flotante, la lectura de los datos llevará más tiempo. Esa es la respuesta ingenua. En un IA32 moderno, todo depende de la procedencia de los datos. Si está en la caché L1, la carga es insignificante siempre que los datos provengan de una sola línea de caché. Si abarca más de una línea de caché, hay una pequeña sobrecarga. Si es de L2, lleva un poco más de tiempo, si está en la RAM, es más largo aún y, finalmente, si está en el disco, es mucho tiempo. Por tanto, la elección de flotante o doble es menos importante que la forma en que se utilizan los datos. Si desea hacer un pequeño cálculo con muchos datos secuenciales, es preferible un tipo de datos pequeño. Hacer muchos cálculos en un conjunto de datos pequeño le permitiría usar tipos de datos más grandes con un efecto significativo. Si tu' Al acceder a los datos de forma muy aleatoria, la elección del tamaño de los datos no es importante: los datos se cargan en páginas / líneas de caché. Entonces, incluso si solo desea un byte de RAM, podría obtener 32 bytes transferidos (esto depende mucho de la arquitectura del sistema). Además de todo esto, la CPU / FPU podría ser superescalar (también conocida como canalización). Entonces, aunque una carga puede tomar varios ciclos, la CPU / FPU podría estar ocupada haciendo otra cosa (una multiplicación, por ejemplo) que oculta el tiempo de carga hasta cierto punto.

  5. El estándar no impone ningún formato particular para valores de coma flotante.

Si tiene una especificación, eso lo guiará a la elección óptima. De lo contrario, depende de la experiencia qué usar.

Skizz
fuente
16

Double es más preciso pero está codificado en 8 bytes. float tiene solo 4 bytes, por lo que hay menos espacio y menos precisión.

Debe tener mucho cuidado si tiene double y float en su aplicación. Tuve un error debido a eso en el pasado. Una parte del código usaba float mientras que el resto del código usaba double. Copiar doble para flotar y luego flotar para doble puede causar un error de precisión que puede tener un gran impacto. En mi caso, era una fábrica de productos químicos ... ojalá no tuviera consecuencias dramáticas :)

¡Creo que es por este tipo de error que el cohete Ariane 6 explotó hace unos años!

Piense detenidamente en el tipo que se utilizará para una variable

luc
fuente
3
Tenga en cuenta que 4/8 bytes para float / double ni siquiera están garantizados, dependerá de la plataforma. Incluso podría ser del mismo tipo ...
sleske
2
El código Ariane 5 intentó convertir un punto flotante de 64 bits, cuyo valor era mayor que 32,767, en un entero de 16 bits con signo. Esto generó una excepción de desbordamiento que hizo que el cohete iniciara su secuencia de autodestrucción. El código en cuestión era un código que se reutilizó de un cohete más antiguo y más pequeño.
cmwt
5

Personalmente voy por el doble todo el tiempo hasta que veo algunos cuellos de botella. Entonces considero moverme para flotar u optimizar alguna otra parte

Eric
fuente
4

Esto depende de cómo implemente el compilador double. Es legal que double y float sean del mismo tipo (y lo es en algunos sistemas).

Dicho esto, si de hecho son diferentes, la cuestión principal es la precisión. Un doble tiene una precisión mucho mayor debido a su diferencia de tamaño. Si los números que está usando comúnmente exceden el valor de un flotante, entonces use un doble.

Varias otras personas han mencionado problemas de desempeño. Eso sería exactamente lo último en mi lista de consideraciones. La corrección debe ser su consideración número uno.

JaredPar
fuente
2

Creo que independientemente de las diferencias (que, como todos señalan, los flotadores ocupan menos espacio y, en general, son más rápidos) ... ¿alguien ha sufrido problemas de rendimiento al usar el doble? Digo que uses double ... y si luego decides "wow, esto es muy lento" ... encuentra tu cuello de botella en el rendimiento (que probablemente no sea el hecho de que usaste double). ENTONCES, si todavía es demasiado lento para usted, vea dónde puede sacrificar algo de precisión y use la flotación.

Tom
fuente
1

Depende en gran medida de la CPU, las compensaciones más obvias son entre precisión y memoria. Con GB de RAM, la memoria no es un gran problema, por lo que generalmente es mejor usardouble s.

En cuanto al rendimiento, depende en gran medida de la CPU. floats normalmente tendrá un mejor rendimiento que doubles en una máquina de 32 bits. En 64 bits, los doublemensajes de correo electrónico a veces son más rápidos, ya que (generalmente) es el tamaño nativo. Aún así, lo que importará mucho más que su elección de tipos de datos es si puede aprovechar o no las instrucciones SIMD en su procesador.

Zifre
fuente
0

double tiene mayor precisión, mientras que los flotantes ocupan menos memoria y son más rápidos. En general, debe usar float a menos que tenga un caso en el que no sea lo suficientemente preciso.

Tal Pressman
fuente
5
En las computadoras modernas típicas, double es tan rápido como flotar.
Thomas Padron-McCarthy