Parece acertado con los beneficios de usar un tipo de punto flotante. Tiendo a diseñar para decimales en todos los casos, y confío en un generador de perfiles para que me haga saber si las operaciones en decimales están causando cuellos de botella o ralentizaciones. En esos casos, haré "down cast" para duplicar o flotar, pero solo lo haré internamente, y trataré cuidadosamente de manejar la pérdida de precisión limitando el número de dígitos significativos en la operación matemática que se realiza.
En general, si su valor es transitorio (no reutilizado), puede usar un tipo de coma flotante. El verdadero problema con los tipos de coma flotante son los siguientes tres escenarios.
- Está agregando valores de coma flotante (en cuyo caso los errores de precisión se combinan)
- Cree valores basados en el valor de coma flotante (por ejemplo, en un algoritmo recursivo)
- Estás haciendo matemáticas con un número muy amplio de dígitos significativos (por ejemplo,
123456789.1 * .000000000000000987654321
)
EDITAR
De acuerdo con la documentación de referencia sobre decimales de C # :
La palabra clave decimal indica un tipo de datos de 128 bits. En comparación con los tipos de coma flotante, el tipo decimal tiene una mayor precisión y un rango más pequeño, lo que lo hace adecuado para cálculos financieros y monetarios.
Entonces, para aclarar mi declaración anterior:
Tiendo a diseñar para decimales en todos los casos, y confío en un generador de perfiles para que me haga saber si las operaciones en decimales están causando cuellos de botella o ralentizaciones.
Solo he trabajado en industrias donde los decimales son favorables. Si está trabajando en motores de gráficos o gráficos, probablemente sea mucho más beneficioso diseñar para un tipo de coma flotante (flotante o doble).
El decimal no es infinitamente preciso (es imposible representar una precisión infinita para no integral en un tipo de datos primitivo), pero es mucho más preciso que el doble:
- decimal = 28-29 dígitos significativos
- doble = 15-16 dígitos significativos
- flotante = 7 dígitos significativos
EDITAR 2
En respuesta al comentario de Konrad Rudolph , el ítem # 1 (arriba) es definitivamente correcto. La agregación de la imprecisión se compone de hecho. Consulte el siguiente código para ver un ejemplo:
private const float THREE_FIFTHS = 3f / 5f;
private const int ONE_MILLION = 1000000;
public static void Main(string[] args)
{
Console.WriteLine("Three Fifths: {0}", THREE_FIFTHS.ToString("F10"));
float asSingle = 0f;
double asDouble = 0d;
decimal asDecimal = 0M;
for (int i = 0; i < ONE_MILLION; i++)
{
asSingle += THREE_FIFTHS;
asDouble += THREE_FIFTHS;
asDecimal += (decimal) THREE_FIFTHS;
}
Console.WriteLine("Six Hundred Thousand: {0:F10}", THREE_FIFTHS * ONE_MILLION);
Console.WriteLine("Single: {0}", asSingle.ToString("F10"));
Console.WriteLine("Double: {0}", asDouble.ToString("F10"));
Console.WriteLine("Decimal: {0}", asDecimal.ToString("F10"));
Console.ReadLine();
}
Esto genera lo siguiente:
Three Fifths: 0.6000000000
Six Hundred Thousand: 600000.0000000000
Single: 599093.4000000000
Double: 599999.9999886850
Decimal: 600000.0000000000
Como puede ver, a pesar de que estamos agregando desde la misma fuente constante, los resultados del doble son menos precisos (aunque probablemente se redondearán correctamente), y el flotador es mucho menos preciso, hasta el punto en que se ha reducido a solo Dos dígitos significativos.