Precisión de un double

05/11/2003 - 14:15 por Sergio | Informe spam
Alguien sabe como hacer para que un double solo trabaje con dos decimales?
Lo necesito para comparar un double con otro dentro de un bucle incremental,
y si necesito comprobar toda la parte decimal de cada unidad el ordenador
tarda bastante en pasar de 1 a 2 en el valor de la variable, por ejemplo.
Gracias de antemano.

Preguntas similare

Leer las respuestas

#6 KAKATUO
11/11/2003 - 23:32 | Informe spam
Yo no veo el problema, he probado esto:

#include <math.h>
#include <stdio.h>

int main(int argc, char* argv[])
{
double i;
double aux;
for (i = 1;i < 2;i = i + 0.001) {
aux = floor(i*100)/100;
printf("aux = %f", aux);
}
return 0;
}

y me salen todos los números de 1.000000 a 1.990000 con sólo los cuatro
últimos decimales a cero, incluido el 1.500000
¿Será cuestión del procesador?

Saludos

"Javier Ariza Ayuso" escribió en el
mensaje news:Fk0sb.997494$
Es normal, hay ciertos valores, como podría ser el 0,15, que no se puede
representar en doble precisión, pero sí el 0,1499999999999 que, a pesar de
ser prácticamente igual a 0,15 no lo es teóricamente, con lo que la
condición no se cumple. En general no deberías usar sentencias


condicionales
con números de coma flotante; redondea y compara enteros.

Prueba esto:

(entiendo que limite es un double en el que pretendes tener un un valor de
dos decimales; si es un entero puedes quitar el floor del segundo


argumento
del for...)
int i;
for(i=0; i<floor(limite*100); i++) {
if(i == floor(valor*100)) {...}
}

en {...} debería entrar con la condición que pretendías. Nota que ahora
todas las comparaciones las haces con enteros, y ninguno con coma


flotante.


Un saludo.

"Sergio" escribió en el mensaje
news:%
> El caso es que uso una función que me devuelve un double, y esa función


es
> de un ocx que no controlo, es por eso por lo que tengo que trabajar con
> doubles. He probado lo que me has dicho y me funciona solo si el número
con
> el que lo comparo no es multiplo de 3. Y no entiendo muy bien porqué.
> El bucle es así:
> double i;
> double aux;
> for (i = 0;i < limite;i = i + 0.01) {
> aux = floor(i*100)/100;
> if (aux == valor) {...} //valor es el double que me ha devuelto la
> funcion del ocx
> }
> pues si i debería ser igual a por ejemplo 0.15 el valor que muestra es
> 0.14999999999
>
> De todos modos gracias, ya se por donde tirar, a ver que encuentro.
>
>


Respuesta Responder a este mensaje
#7 Javier Ariza Ayuso
12/11/2003 - 09:45 | Informe spam
Hola Kakatuo.

El problema está al comparar. Cuando tú haces un printf(%f) no te imprime el
valor que en realidad tiene, te redondea al número de decimales que tenga
por defecto (o al que le pongas como %0.nf) y eso imprime, pero el valor es
otro, es decir, aunque te haya imprimido 0,01 en realidad puede que el valor
sea 0,0099999999999999, con lo que al hacer comparaciones 0,01 !0,00999999999999

Lo de la IEEE lo desconocía, parece lógico, pero no me gusta porque esa
epsilon debe tener un valor concreto (en matemáticas no es concreto, es un
valor infinitesimal), con lo que dependes del compilador.

En cuanto a la solución que te dí el otro día, debes perdonarme porque
efectivamente tiene un error: y es que confundí la función floor() con el
redondeo al valor más próximo.

Dado que no he encontrado una función concreta que redondee al valor más
próximo, vamos a usar la función sprintf para hacerlo:

int i;
char svalor[20];
for(i=0; i<ceil(limite*100); i++) { //aquí no hace falta redondear, pero sí
se debe poner ceil en lugar de floor porque la
//condición es estricta;
pondríamos floor si la condición fuese < o sprintf(svalor,"%.0f",valor*100); //en svalor tenemos valor*100
redondeado al entero mas próximo
if(i == atoi(svalor)) {...} //atoi() pasa un string con un numero a un
int.
}


De todas formas, puede que ahora sí te funcione la comparación de doubles,
ya que lo hemos recortado con sprintf y ambos comparandos se representarían
igual con el mismo valor. Por curiosidad prueba esto también:

double i;
double aux;
char cad[20];
for (i = 0;i < limite;i += 0.01) {
sprintf(cad,"%.2f",valor);
aux = atof(cad);
if (aux == i) {...}
}


Ya dirás...

Saludos.


"KAKATUO" escribió en el mensaje
news:boro2f$nq0$08$
Yo no veo el problema, he probado esto:

#include <math.h>
#include <stdio.h>

int main(int argc, char* argv[])
{
double i;
double aux;
for (i = 1;i < 2;i = i + 0.001) {
aux = floor(i*100)/100;
printf("aux = %f", aux);
}
return 0;
}

y me salen todos los números de 1.000000 a 1.990000 con sólo los cuatro
últimos decimales a cero, incluido el 1.500000
¿Será cuestión del procesador?

Saludos

"Javier Ariza Ayuso" escribió en el
mensaje news:Fk0sb.997494$
> Es normal, hay ciertos valores, como podría ser el 0,15, que no se puede
> representar en doble precisión, pero sí el 0,1499999999999 que, a pesar


de
> ser prácticamente igual a 0,15 no lo es teóricamente, con lo que la
> condición no se cumple. En general no deberías usar sentencias
condicionales
> con números de coma flotante; redondea y compara enteros.
>
> Prueba esto:
>
> (entiendo que limite es un double en el que pretendes tener un un valor


de
> dos decimales; si es un entero puedes quitar el floor del segundo
argumento
> del for...)
> int i;
> for(i=0; i<floor(limite*100); i++) {
> if(i == floor(valor*100)) {...}
> }
>
> en {...} debería entrar con la condición que pretendías. Nota que ahora
> todas las comparaciones las haces con enteros, y ninguno con coma
flotante.
>
>
> Un saludo.
>
> "Sergio" escribió en el mensaje
> news:%
> > El caso es que uso una función que me devuelve un double, y esa


función
es
> > de un ocx que no controlo, es por eso por lo que tengo que trabajar


con
> > doubles. He probado lo que me has dicho y me funciona solo si el


número
> con
> > el que lo comparo no es multiplo de 3. Y no entiendo muy bien porqué.
> > El bucle es así:
> > double i;
> > double aux;
> > for (i = 0;i < limite;i = i + 0.01) {
> > aux = floor(i*100)/100;
> > if (aux == valor) {...} //valor es el double que me ha devuelto la
> > funcion del ocx
> > }
> > pues si i debería ser igual a por ejemplo 0.15 el valor que muestra es
> > 0.14999999999
> >
> > De todos modos gracias, ya se por donde tirar, a ver que encuentro.
> >
> >
>
>


Respuesta Responder a este mensaje
#8 Sergio
12/11/2003 - 09:58 | Informe spam
He probado el programilla que has puesto y no he tenido ningún problema,
pero sale cada número 10 veces, cosa que se soluciona cambiando 0.001 por
0.01, lógico.
Y he probado a sacar a un fichero los valores de mi bucle y en el fichero
salen perfectamente, pero trazando los valores dentro del visual se que sus
valores son completamente distintos, si en el fichero su valor es 0.01
trazando el valor se que es 0.009999999998. Lo cual no me vale.
Respuesta Responder a este mensaje
#9 Sergio
12/11/2003 - 10:02 | Informe spam
A que te refieres con lo de epsilon? Puedes ser mas explicito o poner un
ejemplillo?
Respuesta Responder a este mensaje
#10 Javier Ariza Ayuso
12/11/2003 - 10:37 | Informe spam
Es por lo que le he puesto a Kakatuo, todo depende de cómo tracées. Al
imprimir siempre va a redondear, no te fies, el valor que en realidad tiene
es otro. Debes redondear y usar ese redondeo para hacer comparaciones.

Sinceramente, todavía no veo cuál es tu problema no sé por qué esto te
da tantos quebraderos de cabeza

Saludos.



"Sergio" escribió en el mensaje
news:%
He probado el programilla que has puesto y no he tenido ningún problema,
pero sale cada número 10 veces, cosa que se soluciona cambiando 0.001 por
0.01, lógico.
Y he probado a sacar a un fichero los valores de mi bucle y en el fichero
salen perfectamente, pero trazando los valores dentro del visual se que


sus
valores son completamente distintos, si en el fichero su valor es 0.01
trazando el valor se que es 0.009999999998. Lo cual no me vale.


Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida