¿Cuál es la diferencia entre float y double?
He leÃdo sobre la diferencia entre precisión doble y precisión simple. Sin embargo, en la mayorÃa de los casos, float
y double
parecen ser intercambiables, es decir, el uso de uno u otro no parece afectar a los resultados. Es este realmente el caso? ¿Cuándo son intercambiables los flotadores y los dobles? ¿Cuáles son las diferencias entre ellos?
11 answers
Enorme diferencia.
Como su nombre indica, un double
tiene 2 veces la precisión de float
[1]. En general, a double
tiene 15 dÃgitos decimales de precisión, mientras que float
tiene 7.
Asà es como se calcula el número de dÃgitos:
double
tiene 52 bits mantissa + 1 bit oculto: log(253)÷log (10) = 15,95 dÃgitos
float
tiene 23 bits mantissa + 1 bit oculto: log(224)÷log (10) = 7.22 dÃgitos
Esta pérdida de precisión podrÃa conducir a errores de truncamiento mucho más fáciles de flotar hacia arriba, por ejemplo,
float a = 1.f / 81;
float b = 0;
for (int i = 0; i < 729; ++ i)
b += a;
printf("%.7g\n", b); // prints 9.000023
Mientras que
double a = 1.0 / 81;
double b = 0;
for (int i = 0; i < 729; ++ i)
b += a;
printf("%.15g\n", b); // prints 8.99999999999996
También, el valor máximo de float es aproximadamente 3e38
, pero double es aproximadamente 1.7e308
, por lo que usar float
puede golpear "infinito" (es decir, un número especial de punto flotante) mucho más fácilmente que double
para algo simple, por ejemplo, computando el factorial de 60.
Durante las pruebas, tal vez algunos casos de prueba contengan estos números enormes, lo que puede causar su programas que fallan si usa flotadores.
Por supuesto, a veces, incluso double
no es lo suficientemente preciso, por lo tanto, a veces tenemos long double
[1] (el ejemplo anterior da 9.0000000000000000066 en Mac), pero todos los tipos de coma flotante sufren de errores de redondeo , por lo que si la precisión es muy importante (por ejemplo, procesamiento de dinero) debe usar int
o una clase de fracción.
Además, no use +=
para sumar muchos números de coma flotante, ya que los errores se acumulan pronto. Si estás usando Python, usa fsum
. De lo contrario, intente implementar el algoritmo de suma de Kahan .
[1]: Los estándares C y C++ no especifican la representación de float
, double
y long double
. Es posible que los tres se implementen como IEEE de doble precisión. Sin embargo, para la mayorÃa de las arquitecturas (gcc, MSVC; x86, x64, ARM) float
es de hecho un número de coma flotante de precisión simple IEEE (binary32), y double
es un IEEE número de punto flotante de doble precisión (binary64).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-10 10:55:48
Esto es lo que dicen los estándares C99 (ISO-IEC 9899 6.2.5 §10) o C++2003 (ISO-IEC 14882-2003 3.1.9 §8):
Hay tres tipos de coma flotante:
float
,double
, ylong double
. El tipodouble
proporciona al menos tanta precisión comofloat
, y el tipolong double
proporciona al menos tanta precisión comodouble
. El conjunto de valores del tipofloat
es un subconjunto del conjunto de valores del tipodouble
; el conjunto de valores del tipodouble
es un subconjunto del conjunto de valores del tipolong double
.
El estándar C++ añade:
La representación de valor de los tipos de coma flotante está definida por la implementación.
Yo sugerirÃa echar un vistazo a la excelente Lo que Todo CientÃfico de la Computación Debe Saber Acerca de la Aritmética de Coma Flotante que cubre el estándar de coma flotante IEEE en profundidad. Aprenderá sobre los detalles de la representación y se dará cuenta de que hay un equilibrio entre magnitud y precisión. La precisión de la la representación de coma flotante aumenta a medida que la magnitud disminuye, por lo tanto, los números de coma flotante entre -1 y 1 son los que tienen más precisión.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-06 17:29:32
Dada una ecuación cuadrática: x2 - 4.0000000 x + 3.9999999 = 0, las raÃces exacta a 10 dÃgitos significativos son, r1 = 2.000316228 y r2 = 1.999683772.
Usando float
y double
, podemos escribir un programa de prueba:
#include <stdio.h>
#include <math.h>
void dbl_solve(double a, double b, double c)
{
double d = b*b - 4.0*a*c;
double sd = sqrt(d);
double r1 = (-b + sd) / (2.0*a);
double r2 = (-b - sd) / (2.0*a);
printf("%.5f\t%.5f\n", r1, r2);
}
void flt_solve(float a, float b, float c)
{
float d = b*b - 4.0f*a*c;
float sd = sqrtf(d);
float r1 = (-b + sd) / (2.0f*a);
float r2 = (-b - sd) / (2.0f*a);
printf("%.5f\t%.5f\n", r1, r2);
}
int main(void)
{
float fa = 1.0f;
float fb = -4.0000000f;
float fc = 3.9999999f;
double da = 1.0;
double db = -4.0000000;
double dc = 3.9999999;
flt_solve(fa, fb, fc);
dbl_solve(da, db, dc);
return 0;
}
Ejecutar el programa me da:
2.00000 2.00000
2.00032 1.99968
Tenga en cuenta que los números no son grandes, pero aún asà obtiene efectos de cancelación usando float
.
(De hecho, lo anterior no es el mejor forma de resolver ecuaciones cuadráticas usando números de coma flotante de precisión simple o doble, pero la respuesta permanece sin cambios incluso si se usa un método más estable.)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-05 17:57:25
- Un doble es 64 y una sola precisión (flotador) es de 32 bits.
- El doble tiene una mantisa mayor (los bits enteros del número real).
- Cualquier inexactitud será menor en el doble.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-05 12:53:20
El tamaño de los números involucrados en los cálculos de punto flotante no es lo más relevante. Es el cálculo que se está realizando que es relevante.
En esencia, si está realizando un cálculo y el resultado es un número irracional o decimal recurrente, entonces habrá errores de redondeo cuando ese número se aplaste en la estructura de datos de tamaño finito que está utilizando. Dado que double es el doble del tamaño de float, el error de redondeo será mucho más pequeño.
Las pruebas pueden usar especÃficamente números que causarÃan este tipo de error y, por lo tanto, probaron que habÃa utilizado el tipo apropiado en su código.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-10 11:05:03
Los flotadores tienen menos precisión que los dobles. Aunque ya lo sabes, lee Lo Que DeberÃamos Saber Sobre la Aritmética de Coma Flotante para una mejor comprensión.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-05 13:09:51
Tipo flotador, 32 bits de largo, tiene una precisión de 7 dÃgitos. Si bien puede almacenar valores con un rango muy grande o muy pequeño (+/- 3.4 * 10^38 o * 10^-38), tiene solo 7 dÃgitos significativos.
El tipo doble, de 64 bits de largo, tiene un rango más grande (*10^+/-308) y una precisión de 15 dÃgitos.
El tipo long double es nominalmente de 80 bits, aunque un emparejamiento compilador/sistema operativo dado puede almacenarlo como 12-16 bytes para propósitos de alineación. El doble largo tiene un exponente que simplemente ridÃculamente enorme y debe tener precisión de 19 dÃgitos. Microsoft, en su sabidurÃa infinita, limita el doble largo a 8 bytes, lo mismo que el doble simple.
En términos generales, solo use type double cuando necesite un valor/variable de punto flotante. Los valores literales de coma flotante utilizados en expresiones se tratarán como dobles por defecto, y la mayorÃa de las funciones matemáticas que devuelven valores de coma flotante devuelven dobles. Te ahorrarás muchos dolores de cabeza y encasillamientos si usas doble.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-17 23:29:38
Me encontré con un error que me llevó una eternidad averiguar y potencialmente puede darle un buen ejemplo de precisión de flotador.
#include <iostream>
#include <iomanip>
int main(){
for(float t=0;t<1;t+=0.01){
std::cout << std::fixed << std::setprecision(6) << t << std::endl;
}
}
La salida es
0.000000
0.010000
0.020000
0.030000
0.040000
0.050000
0.060000
0.070000
0.080000
0.090000
0.100000
0.110000
0.120000
0.130000
0.140000
0.150000
0.160000
0.170000
0.180000
0.190000
0.200000
0.210000
0.220000
0.230000
0.240000
0.250000
0.260000
0.270000
0.280000
0.290000
0.300000
0.310000
0.320000
0.330000
0.340000
0.350000
0.360000
0.370000
0.380000
0.390000
0.400000
0.410000
0.420000
0.430000
0.440000
0.450000
0.460000
0.470000
0.480000
0.490000
0.500000
0.510000
0.520000
0.530000
0.540000
0.550000
0.560000
0.570000
0.580000
0.590000
0.600000
0.610000
0.620000
0.630000
0.640000
0.650000
0.660000
0.670000
0.680000
0.690000
0.700000
0.710000
0.720000
0.730000
0.740000
0.750000
0.760000
0.770000
0.780000
0.790000
0.800000
0.810000
0.820000
0.830000
0.839999
0.849999
0.859999
0.869999
0.879999
0.889999
0.899999
0.909999
0.919999
0.929999
0.939999
0.949999
0.959999
0.969999
0.979999
0.989999
0.999999
Como puede ver después de 0.83, la precisión disminuye significativamente.
Sin embargo, si configuro t
como double, tal problema no sucederá.
Me tomó cinco horas darme cuenta de este error menor, que arruinó mi programa.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-10 11:06:08
Al usar números de coma flotante, no puede confiar en que sus pruebas locales sean exactamente las mismas que las pruebas que se realizan en el lado del servidor. El entorno y el compilador son probablemente diferentes en su sistema local y donde se ejecutan las pruebas finales. He visto este problema muchas veces antes en algunas competiciones de TopCoder, especialmente si intentas comparar dos números de coma flotante.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-05 13:00:57
Las operaciones de comparación integradas difieren como cuando se comparan 2 números con coma flotante, la diferencia en el tipo de datos (es decir, flotante o doble) puede dar lugar a resultados diferentes.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-05 01:35:45
A diferencia de un int
(número entero), un float
tiene un punto decimal, y asà puede un double
.
Pero la diferencia entre los dos es que a double
es dos veces más detallada que a float
, lo que significa que puede tener el doble de la cantidad de números después del punto decimal.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-05 12:10:09