2010-02-08 17 views
10

No estoy seguro de cómo lidiar con excepciones de coma flotante en C o C++. De wiki, existen los siguientes tipos de excepciones de punto flotante:Tratando con excepciones de punto flotante

IEEE 754 specifies five arithmetic errors that are to be recorded in "sticky bits" (by default; note that trapping and other alternatives are optional and, if provided, non-default). 

* inexact, set if the rounded (and returned) value is different from the mathematically exact result of the operation. 
* underflow, set if the rounded value is tiny (as specified in IEEE 754) and inexact (or maybe limited to if it has denormalisation loss, as per the 1984 version of IEEE 754), returning a subnormal value (including the zeroes). 
* overflow, set if the absolute value of the rounded value is too large to be represented (an infinity or maximal finite value is returned, depending on which rounding is used). 
* divide-by-zero, set if the result is infinite given finite operands (returning an infinity, either +∞ or −∞). 
* invalid, set if a real-valued result cannot be returned (like for sqrt(−1), or 0/0), returning a quiet NaN. 

es que cuando cualquier tipo de excepciones anteriores sucede, el programa se cierra de forma imprevista? ¿O el programa llevará este error sin mencionar nada y por lo tanto hará que el error sea difícil de depurar?

¿Es capaz un compilador como gcc de dar una advertencia para algún caso obvio?

Qué puedo hacer durante mi programa de codificación para notificar cuando ocurre el error y qué tipos se cuando sucede, de modo que pueda localizar fácilmente el error en mi código? Proporcione soluciones en los casos C y C++.

¡Gracias y saludos!

+0

es probable que las respuestas sean específicas de un sistema operativo. ¿Tienes uno en mente? –

+0

Tanto Linux como Windows, aunque ahora estoy usando Linux con más frecuencia. – Tim

+0

No veo cómo la semántica de coma flotante definida por ISO/IEEE dependerá del sistema operativo. – Jeff

Respuesta

6

En Linux puede usar la extensión GNU feenableexcept (oculta justo en la parte inferior de la página) para activar la captura de excepciones de coma flotante; si lo hace, recibirá la señal SIGFPE cuando ocurra una excepción que usted puede atrapar en su depurador. Pero ten cuidado ya que a veces la señal se tira de la instrucción punto flotante después el que ha hecho la causa del problema, dando información engañosa línea en el depurador!

+0

¡Gracias, Mike! si sin llamar feible excepto, ¿es imposible que SIGFPE sea una trampa? Si solo uso la biblioteca estándar C para especificar un controlador para SIGFPE a través de signal() sin llamar a feenable excepto en la extensión GNU, ¿hará que mi programa reciba SIGFPE? – Tim

11

hay muchas opciones, pero el general y también la filosofía introducida por defecto es 754 a no trampa, pero en su lugar para producir resultados especiales, como infinitos que pueden o no pueden aparecer en los resultados importantes.

Como resultado, las funciones que ponen a prueba el estado de las operaciones individuales no se utilizan tan a menudo como las funciones que ponen a prueba las representaciones de resultados.

Véase, por ejemplo ...

LIST OF FUNCTIONS 

Each of the functions that use floating-point values are provided in sin- 
gle, double, and extended precision; the double precision prototypes are 
listed here. The man pages for the individual functions provide more 
details on their use, special cases, and prototypes for their single and 
extended precision versions. 

int fpclassify(double) 
int isfinite(double) 
int isinf(double) 
int isnan(double) 
int isnormal(double) 
int signbit(double) 

Actualización: Para cualquier persona que realmente piensa operaciones FPU generan SIGFPE en un caso por defecto en estos días, les animo a probar este programa. Puede generar fácilmente subdesbordamiento, desbordamiento y división por cero. Lo que no va a generar (a menos que se ejecuta en el último VAX sobrevivir o de un no-RISC 754) es SIGFPE:

#include <stdio.h> 
#include <stdlib.h> 
int main(int ac, char **av) { return printf("%f\n", atof(av[1])/atof(av[2])); } 
+0

Debo agregar que de todos modos no le importan muchas de las piezas adhesivas. Underflow es raro y casi lo mismo que cero. Inexact es demasiado común para preocuparse. – DigitalRoss

+0

Gracias! Probar el resultado de cada expresión parece demasiado para manejar en el código. Incluso con las pruebas de algunos resultados que se consideran importantes, es muy probable que los resultados sin pruebas arrojen excepciones. Todo lo que espero hacer es detectar la excepción para informar dónde ocurre y de qué tipo es. – Tim

+0

No habrá una excepción y no es necesario que realice una prueba después de las operaciones. C99 introdujo funciones para probar los bits adhesivos de la FPU, pero todavía no están disponibles universalmente y, aunque lo fueran, no querría perder el tiempo. – DigitalRoss

2

diferentes compiladores manejan estos errores en diferentes maneras.

inexactitud es casi siempre el resultado de la división de números con un valor absoluto mayor que uno (quizás a través de funciones de Trancendental). Agregar, restar y multiplicar números con un valor absoluto> 1.0 solo puede generar un desbordamiento.

subdesbordamiento no ocurre muy a menudo, y probablemente no será una preocupación en los cálculos normales, excepto para las funciones iteradas como serie de Taylor.

El desbordamiento es un problema que generalmente se puede detectar mediante algún tipo de comparación "infinito", los diferentes compiladores varían.

división por cero es bastante notable ya que su programa (debe) choque si usted no tiene un controlador de errores. Controlar dividendos y divisores ayudará a evitar el problema.

Las respuestas inválidas por lo general se capturan sin controladores de errores especiales con algún tipo de error de DOMINIO impreso.

[EDIT]

Esto podría ayudar: (numérica Guía de Cálculo por Sun) http://docs.sun.com/source/806-3568/

0

En Linux, puede interceptar estas excepciones atrapando la señal SIGFPE. Si no hace nada, estas excepciones darán por terminado su programa. Para configurar un controlador, use la función de señal, pasando la señal que desea tener atrapada, y la función a llamar en caso de que la señal se dispare.

+0

Gracias! ¿Es posible saber e imprimir dónde ocurre la excepción en la función que maneja la señal? – Tim

+0

Esto no es verdad. En general, solo los sistemas anteriores a 754 generan SIGFPE para operaciones individuales. Además, cosas como inexacta y underflow nunca han sido excepciones. Este programa se puede generar para generar x/0, desbordamiento y subdesbordamiento. No generará un SIGFPE.'#include #include int main (int ac, char ** av) {return printf ("% f \ n ", atof (av [1])/atof (av [2])); } ' – DigitalRoss

1

C99 introduce funciones para el manejo de excepciones de punto flotante. Antes de una operación de punto flotante, puede usar feclearexcept() para borrar cualquier excepción pendiente. Después de la (s) operación (es), puede usar fetestexcept() para probar qué banderas de excepción están establecidas.

4

En Windows con Visual C++, se puede controlar la cual las excepciones de punto flotante son desenmascarados usando _control87() etc.. Las excepciones de punto flotante desenmascaradas generan excepciones estructuradas, que pueden manejarse usando __try/__except (y un par de otros mecanismos). Esto es completamente dependiente de la plataforma.

Si deja las excepciones de punto flotante enmascaradas, otro enfoque dependiente de la plataforma para detectar estas condiciones es borrar el estado de punto flotante usando _clear87() etc., realizar cálculos y consultar el estado de coma flotante con _status87() etc..

Es todo esto nada mejor que la sugerencia de comprobar el resultado de DigitalRoss? En la mayoría de los casos, no lo es. Si necesita detectar (o controlar) el redondeo (lo cual es poco probable), ¿entonces?

En Windows con Borland/CodeGear/Embarcadero C++, algunas excepciones de coma flotante se desenmascaran de forma predeterminada, lo que a menudo causa problemas al utilizar bibliotecas de terceros que no se probaron con excepciones de coma flotante sin máscara.

Cuestiones relacionadas