Foros del Web » Programación para mayores de 30 ;) » C/C++ »

Saber si un double se ha desbordado

Estas en el tema de Saber si un double se ha desbordado en el foro de C/C++ en Foros del Web. Hola amigos estoy trabajando con un pequeñísimo proyecto de C que trabaja con fuerza bruta y doubles y quería saber como detectar si se ha ...
  #1 (permalink)  
Antiguo 15/05/2016, 15:30
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 1 mes
Puntos: 3
Saber si un double se ha desbordado

Hola amigos estoy trabajando con un pequeñísimo proyecto de C que trabaja con fuerza bruta y doubles y quería saber como detectar si se ha desbordado al incrementarlo o al introducir un valor con scanf. ¿pueden ayudarme?
Gracias de antemano.
  #2 (permalink)  
Antiguo 16/05/2016, 02:01
Avatar de leosansan  
Fecha de Ingreso: mayo-2012
Ubicación: GRAN CANARIA
Mensajes: 194
Antigüedad: 11 años, 10 meses
Puntos: 49
Respuesta: Saber si un double se ha desbordado

Código C++:
Ver original
  1. .......
  2. #include <float.h>
  3. .......
  4. double num = 108.3e300, num1 , incremento = 100;
  5.  
  6. (DBL_MAX - 100 < num) ? puts ("SUPERA EL VALOR MAX DE DOUBLE") : puts ("NO SUPERA EL VALOR MAX DE DOUBLE");
  7.  
  8. printf("%e    num = %e\n",DBL_MAX , num);
  9. ......

Última edición por leosansan; 16/05/2016 a las 02:06
  #3 (permalink)  
Antiguo 16/05/2016, 03:46
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 1 mes
Puntos: 3
Respuesta: Saber si un double se ha desbordado

No entiendo exactamente lo que haces ¿le restas el incremento para ver si desborda?
Otra cosa es como saber si el valor añadido con scanf lo desborda.
  #4 (permalink)  
Antiguo 16/05/2016, 05:27
Avatar de leosansan  
Fecha de Ingreso: mayo-2012
Ubicación: GRAN CANARIA
Mensajes: 194
Antigüedad: 11 años, 10 meses
Puntos: 49
Respuesta: Saber si un double se ha desbordado

Ejemplo:
MAX = 10 , Incremento = 5 , numero = 7
si 10 - 5 < 7 ==> nuevo numero = 7 + 5 = 12 > MAX y no vale ¡¡¡¡¡

Lo del scanf a bote pronto no se se ocurre ya que lo traga todo.
  #5 (permalink)  
Antiguo 16/05/2016, 09:48
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 1 mes
Puntos: 3
Respuesta: Saber si un double se ha desbordado

Lo único que se me ocurre es usar float.h y obtener el valor máximo de un float y luego con scanf capturar una cadena y contar los caracteres de la parte entera y los de la parte decimal. Sabiendo el máximo de caracteres de la parte entera comparo ambas cadenas para ver si la que introduje es más grande y si no lo es sigo. Luego empiezo a comparar de izquierda a derecha si tiene el mismo número de caracteres enteros mirando que no sea mayor que el máximo permitido y si es menor no desborda y uso atolf o sscanf para convertir la cadena. Esa es mi idea pero no se cual es el valor máximo de un double porque como se muestra con notación científica...
  #6 (permalink)  
Antiguo 16/05/2016, 11:01
Avatar de leosansan  
Fecha de Ingreso: mayo-2012
Ubicación: GRAN CANARIA
Mensajes: 194
Antigüedad: 11 años, 10 meses
Puntos: 49
Respuesta: Saber si un double se ha desbordado

Si quieres ver el máximo double imprime algo como:

Código C++:
Ver original
  1. printf("%lf\n",DBL_MAX );
  #7 (permalink)  
Antiguo 16/05/2016, 13:47
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 1 mes
Puntos: 3
Respuesta: Saber si un double se ha desbordado

Si pero eso me lo imprime con notación científica y no se si el número de dígitos de la parte entera tiene un máximo fijo o puede usar dijimos de la parte decimal. Tampoco se si hay una parte de memoria fija para decimales y otra para la entera. No se si me explico.

Última edición por aguml; 16/05/2016 a las 14:00
  #8 (permalink)  
Antiguo 16/05/2016, 16:03
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 6 meses
Puntos: 204
Respuesta: Saber si un double se ha desbordado

¿Has probado a usar las utilidades de fenv.h?

Esta librería permite leer los flags aritméticos y te puede servir para detectar ciertos problemas al operar con números, como desbordamiento, división por cero, ...
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #9 (permalink)  
Antiguo 17/05/2016, 14:13
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 1 mes
Puntos: 3
Respuesta: Saber si un double se ha desbordado

El problema, como ya me explicaron aquí en otra ocasión, el Flag O se activa al haber overflow pero cuando llamo a scanf la última instrucción no va a producir overflow así que después del scanf no me va a servir de nada comprobar los Flags. atolf en caso de overflow no está definido su comportamiento con lo que no sirve. sscanf no se que pasará si se produce overflow.
  #10 (permalink)  
Antiguo 17/05/2016, 14:49
Avatar de xKuZz  
Fecha de Ingreso: febrero-2015
Ubicación: nullptr
Mensajes: 183
Antigüedad: 9 años, 2 meses
Puntos: 27
Respuesta: Saber si un double se ha desbordado

Como ya te ha dicho eferion lo primero que deberías de hacer es probar con <fenv.h>. El Flag obtenido por las funciones de <fenv.h> NO es un flag de la ALU. No obstante, no todos los compiladores dan soporte a ello en C.

Puedes comprobar rápidamente si eso es una posibilidad linkando con -lm y mostrando todos los warnings (-Wall) y escribiendo el siguiente pragma
Código C:
Ver original
  1. #pragma STDC FENV_ACCESS ON

Si te dice que el pragma no es conocido sólo se me ocurre una idea que no es portable de compilador a compilador. Si el comportamiento por defecto de tu compilador es redondear con roundToEven o roundToNearest el overflow quedará siempre con el valor a infinitivo si es overflow por encima para positivos o -infinitivo si overflow para negativos utilizando la función isinf de math.h
  #11 (permalink)  
Antiguo 17/05/2016, 15:55
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 6 meses
Puntos: 204
Respuesta: Saber si un double se ha desbordado

Tienes que comprender también que la librería estándar de C/C++ aún tiene muchas carencias y es algo a solucionar a medio/largo plazo.

Una prueba de lo que digo es que es imposible hacer una aplicación completa únicamente con la STL... vale, si, se puede hacer si reinventas la rueda y reescribes cosas que ya están hechas en librerías no estándar como BOOST. Este contratiempo es un problema heredado de la época en la que vió la luz el lenguaje. Otros ejemplos los tienes en el soporte nulo (hasta C++17) de una librería estándar de sockets, la carencia total de librerías para leer XML, interfaz gráfica, gestión de la consola... (ojo, hablo de la STL, no de librerías de 3os o de soluciones caseras para suplir estas carencias)

Así que toca hacerse a la idea de que las librerías actuales tienen ciertas limitaciones.

Otra posibilidad es leer el dato como un string y comprobar (por ejemplo con expresiones regulares) que el valor va a estar dentro del rango posible de valores para el tipo elegido... o currarte un tipo propio con más precisión.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #12 (permalink)  
Antiguo 18/05/2016, 00:30
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 1 mes
Puntos: 3
Respuesta: Saber si un double se ha desbordado

Eso último es lo que deseo hacer pero no tengo claro a que se refiere el valor máximo de double. Por ejemplo si fuese 2.3456E+10 entiendo que es máximo es 23456000000 pero ¿que pasa con la parte decimal? O sea, si pongo 2345.99999999999999999999999 ¿que pasaría en este supuesto casi? Como ves seria menor que el máximo pero no se si se puede desbordar con la parte decimal ni la precisión de esta.
  #13 (permalink)  
Antiguo 18/05/2016, 01:56
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 6 meses
Puntos: 204
Respuesta: Saber si un double se ha desbordado

Cita:
Iniciado por aguml Ver Mensaje
Eso último es lo que deseo hacer pero no tengo claro a que se refiere el valor máximo de double. Por ejemplo si fuese 2.3456E+10 entiendo que es máximo es 23456000000 pero ¿que pasa con la parte decimal? O sea, si pongo 2345.99999999999999999999999 ¿que pasaría en este supuesto casi? Como ves seria menor que el máximo pero no se si se puede desbordar con la parte decimal ni la precisión de esta.
Para entender esa parte tienes que saber cómo se almacenan los números decimales en el sistema... ¿has mirado algo sobre ese tema?

  • Bit de signo, exponente y mantisa
  • La mantisa está normalizada, luego siempre falta un bit -> bit fantasma
  • Precisión limitada

Si los conceptos anteriores te suenan a chino entonces deberías darle un repaso a cómo se almacenan los números decimales en el sistema... es la base para entender cómo funcionan :)

Un saludo.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #14 (permalink)  
Antiguo 18/05/2016, 04:24
 
Fecha de Ingreso: junio-2010
Ubicación: Madrid
Mensajes: 620
Antigüedad: 13 años, 10 meses
Puntos: 73
Respuesta: Saber si un double se ha desbordado

En doble precisión (64 bits) tendrás 15-16 dígitos de precisión. Si quieres imprimir más, te imprimirá ceros. Si tienes un desbordamiento, lo que ocurra depende del comilador. Por ejemplo, con Mingw 4.8.1 32 bits, me he encontrado con:

1. Si el desbordamiento es comno consecuencia de cálculos, o haciendo atof() a una cadena de caracteres que se corresponda con un número superior a DBL_MAX, te va a dar un resultado de INF (infinito). El programa no te dará error.

2. Si el desbordamiento es consecuencia de hacer un scanf() para un double e introduces un valor superior a DBL_MAX, el resultado será NaN (Not a Number).

Los valores INF y NaN son combinaciones especiales de bits para un número en coma flotante. Si quieres detalles, mírate la norma IEEE 754.

Si quieres evitar el desbordamiento, comprueba si tienes el tipo long double. Este es un tipo de 80 bits que utiliza el coprocesador de manera interna. Ojo, porque algunos compiladores te aceptarán long double como sinónimo de double. Utiliza sizeof, deberá darte 12 ó 16 bytes, dependiendo de si es un sistema de 32 ó de 64 bits, respectivamente. El rango de long double es de 1.xxxE+4932, con unos 20 dígitos de precisión.
  #15 (permalink)  
Antiguo 18/05/2016, 04:43
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 1 mes
Puntos: 3
Respuesta: Saber si un double se ha desbordado

pues puedo decir que me suena casi todo eso a chino pero he estado experimentando antes de tu respuesta y he visto cosas:
1- No sirve usar:
Código C:
Ver original
  1. double a,b;
  2.     b=a=DBL_MAX;
  3.     a++;
  4.     if(b > a)
  5.        printf("Huvo overflow");
es curioso pero en ese caso a y b valen igual incluso habiendo incrementado una de ellas.

2- No sirve el truco:
Código C:
Ver original
  1. double a=DBL_MAX;
  2.     a++;
  3.  
  4.     __asm{
  5.         pushad
  6.         pushfd
  7.         pop eax
  8.         mov flags, eax
  9.         popfd
  10.         popad
  11.     }
  12.     if(flags & (1<<11))
  13.         printf("Hubo overflow");
No se activa el flag de overflow.

3- Hice esto:
Código C:
Ver original
  1. double a=DBL_MAX;
  2.     a *=2;
Esto me suelta una excepcion diciendo que se ha desbordado. ¿se podria usar try catch para controlar si se produjo overflow en un double? ¿eso seria una locura?
Para controlar la entrada de scanf encontre una solucion mas o menos razonable:
Código C:
Ver original
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <errno.h>
  4. //#include <math.h>
  5.  
  6. #define BEEP 7
  7. #define MAX 20
  8. #define POS_INF 1.0 /0.0;
  9. #define NEG_INF -1.0/0.0;
  10.  
  11. double leer_double(void) {
  12.     double x;
  13.     char a[MAX], *p, c;
  14.    int i, encontrado = 0;
  15.  
  16.     fgets(a, MAX, stdin);
  17.     x = strtod (a, &p);
  18.  
  19.    if(errno == ERANGE){
  20.       printf("%s\n",strerror(errno)); //Huvo overflow
  21.       if(x==0){
  22.          x= NEG_INF;
  23.       }else{
  24.          x= POS_INF;
  25.       }
  26.    }else{
  27.       for(i = 0; i < MAX; i++){
  28.          if(a[i] == '\n'){
  29.             encontrado = 1;
  30.             break;
  31.          }
  32.       }
  33.  
  34.       if(*p != '\n'){
  35.          printf("%c",BEEP); /* Aviso de error */
  36.            printf("Dato incorrecto.\n");
  37.  
  38.          if(encontrado == 0){
  39.             do{ /* Ciclo para vaciar el resto que haya quedado en el buffer stdin */
  40.                  c = getchar();
  41.             }while(c != '\n');
  42.          }
  43.          x=0;
  44.        }
  45.    }
  46.     return x;
  47. }
  48.  
  49. int main() {
  50.     double d;
  51.  
  52.    printf("Introduce un valor: ");
  53.     d = leer_double();
  54.     printf ("retorno: %lf\n", d);
  55.     system("PAUSE");
  56.    return 0;
  57. }
¿que os parece esta solucion? ¿cambiariais algo?
  #16 (permalink)  
Antiguo 18/05/2016, 04:54
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 6 meses
Puntos: 204
Respuesta: Saber si un double se ha desbordado

Cita:
Iniciado por aguml Ver Mensaje
pues puedo decir que me suena casi todo eso a chino
Pues ya tienes deberes antes de seguir investigando... si no entiendes lo que estás manejando no vas a conseguir que funcione.

Cita:
Iniciado por aguml Ver Mensaje
es curioso pero en ese caso a y b valen igual incluso habiendo incrementado una de ellas.
double tiene una precisión determinada, como te ha comentado Fw190. Si tu tienes 1e80 y programas un bucle para que durante 10 años le sume valores de 1 en 1, el resultado final será 1e80 porque la unidad que sumas es tan sumamente pequeña en comparación con el número actual que su valor queda descartado... para entender el por qué es mejor que te documentes un poco ántes.


Cita:
Iniciado por aguml Ver Mensaje
No se activa el flag de overflow.
La misma explicación que en el caso anterior. Esa suma no ha modificado el valor de la variable.

Cita:
Iniciado por aguml Ver Mensaje
Esto me suelta una excepcion diciendo que se ha desbordado. ¿se podria usar try catch para controlar si se produjo overflow en un double? ¿eso seria una locura?
Que te salte una excepción sí es algo característico de tu compilador o de las opciones de compilación... no deberías relajarte y pensar que con un try-catch ya lo tienes todo solucionado.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #17 (permalink)  
Antiguo 18/05/2016, 06:07
 
Fecha de Ingreso: abril-2016
Mensajes: 31
Antigüedad: 8 años
Puntos: 5
Respuesta: Saber si un double se ha desbordado

Prueba
Código C:
Ver original
  1. #include <float.h>
  2. #include <math.h>
  3. #include <stdio.h>
  4.  
  5.  
  6. bool chechSum(double a, double b)
  7. {
  8.     if(copysign(a, b) == a &&
  9.         fabs(b) > DBL_MAX - fabs(a))
  10.         return false;
  11.  
  12.     return true;
  13. }
  14.  
  15.  
  16. int main()
  17. {
  18.     double a = 1.7976931348623158e+308;
  19.     double b = -0.01;
  20.     double s = 0;
  21.  
  22.     if (chechSum(a, b)) {
  23.         s = a + b;
  24.         printf("%f\n", s);
  25.     }
  26.     else
  27.         printf("overflow\n");
  28.  
  29. }
  #18 (permalink)  
Antiguo 18/05/2016, 07:23
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 1 mes
Puntos: 3
Respuesta: Saber si un double se ha desbordado

Bueno pues me tocara leer sobre el tema. ¿sabes de algún escrito o algo donde se trate el tema?
Sobre el último código la verdad es que no se muy bien que hace pero tendría que ser algo más complejo ya que se harían sumas, restas, multiplicaciones, divisiones, raíces cuadradas, y potencias.
  #19 (permalink)  
Antiguo 18/05/2016, 09:44
 
Fecha de Ingreso: abril-2016
Mensajes: 31
Antigüedad: 8 años
Puntos: 5
Respuesta: Saber si un double se ha desbordado

Lo que hace es comprobar antes de sumar (o de la resta) si va a provocar overflow o no. Te faltarían las pruebas para las otras operaciones. Si te vale el C++, este es un buen lugar para empezar http://en.cppreference.com/w/cpp/language/types
  #20 (permalink)  
Antiguo 18/05/2016, 14:38
 
Fecha de Ingreso: junio-2010
Ubicación: Madrid
Mensajes: 620
Antigüedad: 13 años, 10 meses
Puntos: 73
Respuesta: Saber si un double se ha desbordado

Si se trata de un algoritmo de fuerza bruta, no creo que sea conveniente hacer comprobaciones de cada operando antes de operar para ver si va a haber overflow, te podrías eternizar. Si crees que puedes tener overflow de un double, como ya te comenté, prueba a ver si dispones del tipo long double. Otras opciones podrían ser:

En ocasiones, el cambiar el orden de las operaciones puede obrar maravillas.

Utiliza una librería de precisión arbitraria. No indicas qué compilador utilizas, para el compilador GNU tienes la GMP, y buscando podrás encontrar otras.

Algunos compiladores disponen de un tipo qfloat de 384 bits (no, no es un error). Esto te daría unos 100 dígitos de precisión. No recuerdo en este momento el rango, pero creo que es superior al de long double. Con este tipo tienes, por ejemplo, el compilador Lcc-Win32 (creo que hay también una versión para 64 bits).
  #21 (permalink)  
Antiguo 19/05/2016, 11:30
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 1 mes
Puntos: 3
Respuesta: Saber si un double se ha desbordado

Realmente no creo que con las operaciones que realizo se desbordaría pero era por informarme para cuando lo necesitara. Muchas gracias a todos por la info.

Etiquetas: double, int
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 19:19.