Operacion con Double me falla la exactitud

Iniciado por xmbeat92, 13 Diciembre 2011, 19:52 PM

0 Miembros y 1 Visitante están viendo este tema.

xmbeat92

lo que pasa es que he estado buscando porque no me da exacto esto, nunca entra en la condicion, no se que debo hacer para que X me de 0.456, el resultado de X despues de esa operacion es de 0.4560000000000030695446184836328029632568359375

#include <iostream>
using namespace std;
int main(){
   double x=123.456;
   x-=123;
   if (x==0.456){cout<<"Iguales";}
   
}

El hombre encuentra a Dios detrás de cada puerta que la ciencia logra abrir. -Einstein

ApOkAlizE

Juan, yo en las mates soy muy malo pero si el resultado esta bien menos en que las cifras de menor importancia son distintas pdorias provar en cojer por ejemplo solo 3 decimales y así solo comparas si es igual a 0.465 y como te darà pues ya esta, bueno nose si es exactamente eso lo que buscas.
Los virus informaticos son como las personas, hacen lo posible para destruir y hacen lo impossible para no ser destruidos... - ApOkAlizE

xmbeat92

no, de hecho no me ayuda en nada, lo que ando haciendo es algo como esto:

Cadena strStr(double numero){
       Cadena temp;
       long int residuo, i=10,cociente;
       char c;
       while (int(numero)!=0){
           residuo=((int)numero)%i;//123
           numero-=residuo;
           residuo/=(i/10);
           c=residuo+48;
           temp=Cadena(c)+temp;
           i*=10;
       }
       if (numero!=0){
           temp+='.';
           i=10;
           while (numero!=0){
               numero*=10;
               cociente=numero;
               residuo=cociente%10;
               c=residuo+48;
               temp+=c;
               if (numero>0) numero-=residuo;
           }
       }

       return temp;
   }


aun esta terminado para con numeros negativos, pero es aqui donde descubro que mi resultado se ve modificado por las operaciones que hago a dentro
El hombre encuentra a Dios detrás de cada puerta que la ciencia logra abrir. -Einstein

[L]ord [R]NA

#3
Es que estas restando un entero a un punto flotante... prueba con este.
Código (cpp) [Seleccionar]

#include <iostream>
using namespace std;
int main(){
   double x=123.456;
   x-=123.0;
   if (*(int*)&x==0.456)cout<<"Iguales";
   
}


tambien este es valido

Código (cpp) [Seleccionar]

#include <iostream>
using namespace std;
int main(){
   double x=123.456;
   x-=123f;
   if (*(int*)&x==0.456)cout<<"Iguales";
   
}

xmbeat92

Supongo que lo probaste y te da, pero a mi no! o me equivoco, aun no entra en el if, estoy en un procesoador x86 sistema linux si es q afecta en algo pero lo dudo
El hombre encuentra a Dios detrás de cada puerta que la ciencia logra abrir. -Einstein

[L]ord [R]NA

Modifique el codigo nuevamente... lo que sucede es que en los float existe un margen de error, son flotantes y dan un margen de precision, no exactitud.

xmbeat92

ya probe el codigo nuevamente pero aun no me da la condicion, o eso es lo que me trataste de decir hace un momento??
El hombre encuentra a Dios detrás de cada puerta que la ciencia logra abrir. -Einstein

Ferno

¿Podrías probar a truncarlo con 3 decimales significativos, no? Aunque tendrás que preocuparte por los errores de redondeo...

[L]ord [R]NA

Entonces prueba colocando un margen de error... seria lo mas correcto. Como te comente, todo depende de la precision que requieras y agregar el margen de error.

Código (cpp) [Seleccionar]
#include <iostream>
using namespace std;
int main(){
   double x=123.456;
   x-=123.0;
   if (x>=0.4560 && x<0.4561)cout<<"Iguales";

}

raul_samp

Cita de: xmbeat92 en 13 Diciembre 2011, 19:52 PM
lo que pasa es que he estado buscando porque no me da exacto esto, nunca entra en la condicion, no se que debo hacer para que X me de 0.456, el resultado de X despues de esa operacion es de 0.4560000000000030695446184836328029632568359375

#include <iostream>
using namespace std;
int main(){
   double x=123.456;
   x-=123;
   if (x==0.456){cout<<"Iguales";}
   
}


Primero el valor de x no seria el que has dicho sino que seria 0.45600000000000307 porque los doubles no tienen tanta precisión en C++ y todos los dígitos de mas que coges son *****.

Porque pasa esto pues muy fácil los valores de punto flotante generalmente no tienen una representación binaria exacta. De hecho, los diferentes compiladores y arquitecturas de CPU existentes almacenan temporalmente los resultados a diferentes precisiones, por lo que los resultados pueden depender del entorno en que trabajemos y de un montón de cosas más.

Solución también muy fácil ver que los números a comparar se aproximan en un orden de magnitud.

Por ejemplo en nuestro caso seria algo así como:

if(abs(x - 0.456) <= 1e-5)

Si quieres compararlo con un error de +- 10e-5

abs() es la función valor absoluto de la librería cmath.
Yeah Mr. White, yes science!!