Precisión de floats

Started by HaCkZJuaNN, February 05, 2009, 07:36:40 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

HaCkZJuaNN

Sé que quizás esto no se pueda arreglar o sea así por c o lo que sea, pero lo que realmente busco es que alguien me ofrezca una alternativa.

La cuestión es que tengo una función que me calcula las cifras significativas de un número(aunque no estoy seguro de que se llame así), que son el número de cifras entre la cifra más baja que no es 0 y la cifra más alta que no es 0. Por ejemplo, de 12 es 2, de 10 es 1, de 1.25 es 3 y de 101 es 3.

Para ello, mi función coge el número, lo multiplica por 10 hasta que tenga al menos 1 cifra entera, y entonces va multiplicando por 10 y contando mientras comprueba si el valor del float es igual que el valor de otra variable int a la que le asigno el valor del float.

El problema me ha ocurrido concretamente con el número 1.03. He comprobado que al decirle say(variable), me da 1.02999987 o algo así, y claro, cuando llega a 103, que es el momento en el que el entero es igual al float, el entero es 102 y el float es 102.999876..., por lo que no funciona correctamente.

El caso es que no se me ocurre otra manera de hacer este proceso sin que se me jorobe por la precisión de los floats. He probado utilizando float/int == 1 para ver si son iguales y float%int == 0(pero % sólo funciona con ints).

Alguna idea???

Gracias por todo y un saludo.

EDIT: Corrección, el problema no está en la precisión de los floats, sino en la precisión en sus operaciones. Si el 103 directamente lo declaro como 103 no hay problema. El problema es al multiplicar 1.03 por 10 dos veces, que me da 102.99987

EDIT2: También he probado con hacer atoi(ftoa(numero)), es una chapuza, lo sé, pero tampoco funciona.

HaCkZJuaNN

Pffff, acabo de caer en la cuenta de que el problemita de la precisión no sólo afecta a este proceso, me desmonta un montón de cosas que tenía hechas o pensadas... uffff.... Necesito que los números que son enteros lo sigan siendo al hacer operaciones con ellos que en matemáticas teóricas lo harían... No hay ningún modo de evitar este problema???

Prg

#2
amigo, no se qué puedas hacer, pero tengo una idea, prueba con double,
[code language="bennu"]global
double mifloat;[/code]

double es un float más preciso, que en bennu nadie usa,

lo que creo es que el 1.03 no existe concretamente en floats, se usa uno muy similar (1.02999987), pero quizá un double sí pueda representarlo. te advierto, debes usar márgenes de error, pues este error se presentará con muchos otros números, no se diga con pi, e, etc,


amigo, acabo de ver que el double se comporta como int (ya veo porqué nadie lo usa), lástima, sin embargo el float sí presenta 1.03, creo que debes hacer todas tus operaciones con número floats (esto,, tengo entendido en algunos lenguajes funciona).

los strings que mensionabas también pueden ser la solución, quitando el punto mediante regex o algo así, y luego hacer operaciones con int
oye, si pones el código, quizá podamos hacer algo más por tí :) .
en humos puedes mover la camara con los cursores. es necesario para los niveles a partir del dos :)

HaCkZJuaNN

Qué quieres decir con que el double se comporta como int, que no tiene decimales y redondea???

Se me ha ocurrido una forma de solucionarlo, pero es un poco "heavy", preferiría esperar a ver qué otras soluciones me ofrecéis.

SplinterGU

veo que no leen los posts del foro... hace unos pocos post atras repondi lo del tema de la precision de los floats... (incluso, fue hoy mismo)

http://forum.bennugd.org/index.php?topic=439.msg5202
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

HaCkZJuaNN

Sí que lo había leído, pero ahí hablas de dinero, con 2 dígitos siempre, yo lo utilizo para funciones matemáticas, con cualquier número de dígitos, y además como tú mismo has dicho, no es óptimo utilizar el sistema de pasarlo a cadena, etc... De todas maneras ya voy teniendo un esbozo de lo que creo que voy a hacer, pero voy a tener que trabajar mucho, mucho. Según se deduce de ese post, el problema viene de C, no es de bennu, pero no hay ningún modo de solucionarlo de alguna forma sin tener que hacer "chapuzas"??? utilizando otro tipo de dato, o tener la posibilidad de cambiar la forma en que funcionan los floats para lograr mayor precisión(no quiero decir cambiarlo de fondo, sino hacerlo mediante una variable que controla el tipo de floats que se utilizan o algo así).

En cualquier caso, mañana empezaré con esto que tengo pensado. La idea es hacer que cada número sea una combinación de varios ints. La pega con eso es que tengo que hacer funciones para todas las operaciones matemáticas... No voy a ponerme a explicar todo lo que tengo pensado sobre esto. Pero va a ser mucho curre...

De cualquier manera, gracias, y sigo abierto a sugerencias.

SplinterGU

si es 3 digitos es 1000, si es 4 es 10000...
no es de bennu, y diria que tampoco es precisamente de C, sino de la especificacion IEEE... si queres precision no uses coma flotante, usa valores enteros... los tipos de datos de coma flotante no son precisos...
claro que podes usar 2 ints, uno para la parte entera y otro para la decimal, pero visto desde el punto de vista de performance eso no es la mejor idea... y si pensas utilizar mas de 2 ints menos performante aun...
Download Lastest BennuGD Release: http://www.bennugd.org/node/2