• Viernes 1 de Noviembre de 2024, 23:32

Autor Tema:  Precisión  (Leído 1446 veces)

E.Baley

  • Miembro activo
  • **
  • Mensajes: 44
    • Ver Perfil
Precisión
« en: Viernes 29 de Agosto de 2008, 10:37 »
0
Hola amigos, a ver si me podeis ayudar en una duda que me trae de cabeza.

En algún lugar de un programa uso listas de valores en coma flotante. Puesto que cada valor sólo usa como máximo cinco posiciones decimales, me dispongo a usar el tipo que menos recursos necesite, a elegir entre Decimal (16 bytes), Double (8 bytes) y Float (4 bytes). Evidentemente el Float es el más económico en recursos, sobre todo si usamos listas con miles de Floats dentro.

Sin embargo, cuando realizo operaciones en los valores, la precisión se va degradando de forma que siempre obtengo decimales en posiciones que no deberían estar. Para hacerme entender, 0.0075d + 0.0025d debería ser 0.01 sin embargo me sale un número con muchos más decimales que se aproxima mucho al resultado correcto.

El mismo error me ocurre con los Float, únicamente trabajando con Decimal me realiza las operaciones correctamente, pero entonces uso 16 bytes en vez de 4 (4 veces más de espacio en memoria !!).

A modo de ejemplo:

Código: Text
  1. static void Main(string[] args) {
  2.             List<float> listaF = new List<float>();
  3.             float f1 = 0.0075F;
  4.             float incrementoF = 0.0025F;
  5.            
  6.             for (int i = 0; i < 100; i++) {
  7.  
  8.                 // Esto se degrada con el paso de las iteraciones, y adquiere cada vez más decimales
  9.                 f1 = f1 + incrementoF;
  10.                 // Tengo que hacer esto para que pierda los decimales que no interesan
  11.                 //f1 = Single.Parse(f1.ToString("F4"));
  12.                 listaF.Add(f1);
  13.  
  14.                 Console.WriteLine("Posición {0}: {1}", i, f1);
  15.             }
  16.  
  17.             //Poner un punto de interrupción aquí, y mirar la lista en la ventana de "Variables locales" del debugger
  18.             Console.ReadLine();
  19. }
  20.  

Bueno, veréis que la única solución que se me ocurre es truncar los decimales sobrantes convirtiendo a string y volviendo a parsear esa cadena, una solución bastante chapucera que además es poco eficiente. ¿ Cómo debo hacer para que me sume correctamente, sin decimales fantasma ?

gracias.

ProfesorX

  • Moderador
  • ******
  • Mensajes: 796
  • Nacionalidad: mx
    • Ver Perfil
Re: Precisión
« Respuesta #1 en: Viernes 29 de Agosto de 2008, 19:53 »
0
Pues esa es la solucion, usar decimal en lugar de float ;)

La precision de los float es asi, no puedes cambiarla, y aunque trunques, el resultado nunca sera exacto.

Lo mejor es decimal,, ya que es un formato que tiene precision hasta 28 digitos.

La pregunta que debes hacerte no es ¿Cuanto espacio me ocupara? sino ¿Necesito alta precision, porque requiero guardar valores con varios decimale? Si la respuesta es afirmativa, entonces debes usar decimal.

NOTA:
==================================================================
Este foro es para ayudar, aprender, compartir... usenlo para eso,
NO SE RESUELVEN DUDAS POR MENSAJE PRIVADO Y MENOS POR CORREO
==================================================================

E.Baley

  • Miembro activo
  • **
  • Mensajes: 44
    • Ver Perfil
Re: Precisión
« Respuesta #2 en: Viernes 29 de Agosto de 2008, 20:07 »
0
Gracias profe  :D
Definitivamente, parece que usar el tipo Decimal es a la vez la solución y el problema.

Respondiendo a tu pregunta "¿ Necesito alta precision, porque requiero guardar valores con varios decimales ?"
La respuesta es "no" , no necesito alta precisión (todos los valores deben llevar como máximo 5 decimales). Por tanto, usaré el tipo Float.

Sin embargo, al usar el Float, cualquier cálculo sobre ellos (por sencillo que sea) da un resultado erróneo.
Otra solución que encontré es usar Math.Round(unFloat, 5) para redondear al 5º decimal, después de cada operación.
Ahora debo elegir entre tiempo de proceso y uso de memoria.

gracias en cualquier caso.

psikotic

  • Nuevo Miembro
  • *
  • Mensajes: 12
    • Ver Perfil
Re: Precisión
« Respuesta #3 en: Lunes 6 de Octubre de 2008, 18:32 »
0
En realidad se debe a la forma en que son representados los numeros de punto flotante en .NET y en casi cualquier compilador de otros lenguajes se tiene el mismo detalle, si requieres hacer calculos precisos usa Decimal, si no basta con mostrar tu informacion con un Formatter el que usaste "F4", solo usalo a la hora de mostrar al usuario:

Console.WriteLine("Posición {0}: {1:F4}", i, f1);

Mas info en
Código: Text
  1. docs.sun.com/source/806-3568/ncg_goldberg.html
  2.