Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: astinx en 4 Abril 2012, 16:50 pm



Título: Quedarme solo con algunos decimales.
Publicado por: astinx en 4 Abril 2012, 16:50 pm
Hola, tengo un problema muy sencillo y que aún así me sigue quemando el coco.
Tengo una función que me devuelve un float, un float que es el resultado de 10/3, osea 3,333333...
Quiero recortarle algunos decimales cosa de que me quede como 3,333 o 3,3333.
Lo que hago es sencillo, tomo el float en cuestión, lo multiplico por 10⁴, si quiero tener 4 decimales luego de la coma y lo convierto a entero cosa de que me quede: 33333. Luego lo divido a ese entero, casteado a float por 10⁴, para volver a mover los decimales, cosa de que me quede 3,3333. Sin embargo lo que me ocurre es que cuando lo imprimo formateado como %.100f (cosa de ver todos los decimales posibles), me queda 3,333300000000003454345677. Esto me esta volviendo loco, porque solo me sucede con numeros periódicos y es un razonamiento muy sencillo.

El codigo seria algo como
int decimales = 3;
float miNumero = funcion_que_devuelve_float(10,3);
int miNumero2 = (int)(miNumero * pow(10,decimales));
float miNumero = (float)(miNumero2 / pow(10,decimales));

También intente multiplicar en ambos casos, en uno por la potencia negativa y en otro por la positiva, con el mismo resultado.

Muchas gracias por detenerse a leer y saludos.


Título: Re: Quedarme solo con algunos decimales.
Publicado por: Ferno en 4 Abril 2012, 17:53 pm
Esto se debe a que el número 3,3333 que te queda del último cálculo y el casteo a float (simple presición) es irrepresentable perfectamente en una computadora.
Lo que hace la máquina es aproximar este tipo de numeros por el conocido método del "Punto Flotante" que se rige bajo la norma IEEE754.

Se expresan de la forma: mantisa * 2^(exponente) Con la mantisa normalizada (1 =< mantisa < 2).

Lo que hace el micro es (lo explico en simple presición ya que estás usando el tipo float), representar el número utilizando 32 bits. Se utiliza:
1 bit para el signo del número (en este caso 0, positivo)
8 bits para el exponente (con la convención del Exceso-127)
23 bits para la mantisa.

Para el caso particular del 3,3333 éste se representa en binario como 1,10101010101010011001001....(sigue indefinidamente) * 2^(1)

Esto queda, utilizando simple presición:
(signo) | (exponente = 128 (se le suma 127 al exponente 1) ) | mantisa normalizada
0 | 10000000 | 10101010101010011001001

Y el resultado de ésta expresión es el número que se imprime al querer mostrar todos los decimales posibles de tu resultado.

Yo te diría que muestres los decimales que tengas que utilizar, si mostrás todos los posibles, jamás quedará un resultado redondo por lo que expliqué más arriba. Truncalo.
Espero que te sea de ayuda, creí conveniente explicar un poco cómo se maneja el micro en cuanto a números fraccionales.
Saludos!


Título: Re: Quedarme solo con algunos decimales.
Publicado por: astinx en 6 Abril 2012, 00:19 am
Gracias, ahora usando _Decimal64 lo solucione :D


Título: Re: Quedarme solo con algunos decimales.
Publicado por: david_BS en 7 Abril 2012, 20:19 pm

no se si era lo pedido, pero traté de improvisar algo con referencia a eso..

EI: la idea del foro es ayudar y no hacer.