2009-03-30 7 views
9

Me gustaría jugar con esas trampas con fines educativos.¿qué idiomas exponen IEEE 754 trampas para el desarrollador?

Un problema común con el comportamiento predeterminado en el cálculo numérico es que "extrañamos" el Nan (o + -inf) que apareció en una operación incorrecta. El comportamiento predeterminado es la propagación a través del cálculo, pero algunas operaciones (como las comparaciones) rompen la cadena y sueltan el Nan, y el resto del tratamiento continúa sin reconocer la singularidad en los pasos previos del algoritmo.

A veces tenemos formas de reaccionar a este tipo de evento: prolongando una función ("0/0 = 12 en mi caso"), o en simulación de dominio de tiempo lanzando el paso e intentando con otras configuraciones (como predictor, el tamaño del paso o lo que sea).

Así que aquí está mi pregunta: ¿conoce los idiomas que exponen las trampas IEEE754 para el desarrollador? No tengo ganas de jugar con ASM por eso.

Respuesta

0

C y probablemente la mayoría de los lenguajes derivados de él como C++ o python (aunque puede ser un acceso indirecto). Probablemente sea razonable esperar que los idiomas de bajo nivel tengan dicho soporte.

Consulte http://www.math.utah.edu/~beebe/software/ieee/#c-notes que tiene numerosas secuencias de comandos y notas sobre cómo trabajar con números IEEE 754. En particular, of1.c trata con excepciones de coma flotante. Finalmente, desde la fuente http://grouper.ieee.org/groups/754/reading.html que incluye un montón de información útil.

+0

¿Puede ser un poco más específico, por favor? No pude encontrar esto en la documentación, encontré cómo manipular las banderas, pero no cómo establecer una trampa: http://www.opengroup.org/onlinepubs/000095399/basedefs/fenv.h.html – nraynaud

+0

Actualizado con enlaces –

+0

Gracias por los enlaces. Después de mirar el programa C (creo que me veía bien, pero en todo este ruido de preprocesador es difícil ser afirmativo), no veo las trampas expuestas como tales. Solo veo la manipulación de la bandera. El controlador SIG_FPE parece ser un caso espacial para una plataforma. – nraynaud

3

Por lo que yo sé, usted tiene dos opciones para flotar el manejo de excepciones punto en C y C++:

En primer lugar, si se desactiva/mask excepciones de punto flotante (que la mayoría de los ambientes hacen de forma predeterminada), se puede ver si se han producido excepciones de coma flotante llamando al fetestexcept. fetestexcept no está disponible en Visual C++, pero puede robar la implementación de MinGW Runtime con la suficiente facilidad. (Está en el dominio público.) Una vez que se ha marcado una excepción, no se borrará hasta que llame a feclearexcept, por lo que puede llamar a fetestexcept al final de una serie de cálculos para ver si alguno de ellos generó una excepción. Esto no le proporciona las trampas que solicitó, pero le permite probar si se han producido problemas como NaN o +/- inf y reaccionar según sea necesario.

En segundo lugar, puede activar/desactivar las excepciones de punto flotante llamando a feenableexcept en Linux o _controlfp en Windows. La forma en que el sistema operativo maneje una excepción de coma flotante generada por el procesador depende de su sistema operativo.

  • En Linux, el sistema operativo envía una señal SIGFPE, para que pueda instalar un manejador de señales para coger eso y establecer un indicador que le dice a su rutina para reaccionar adecuadamente.
  • En Windows, el sistema operativo invoca el control de excepciones estructurado para convertir la excepción del procesador en una excepción de lenguaje que se puede coger con un bloque de __try/__catch en C o try/catch bloque en C++.
  • Actualización: Para Mac OS X, como se describe en this answer, usted debe ser capaz de activar/desenmascarar excepciones usando _MM_SET_EXCEPTION_MASK de xmmintrin.h, y siempre y cuando se utilizan las opciones del compilador por defecto (es decir, no desactivar SSE) , deberías poder capturar excepciones usando SIGFPE.

(He escrito un poco más sobre este y otros problemas de punto flotante en C y C++ en this blog posting si tiene curiosidad.)

+0

Ese es un buen punto, yo solo estaba jugando con esto, y como me siento afortunado, estoy en una mac con 2 problemas específicos de la plataforma: http://www.gnu.org/software/hello/manual/gnulib/ feenableexcept.html http://lists.apple.com/archives/Darwin-dev/2006/Mar/msg00102.html – nraynaud

+0

La información en el enlace que agregué parece funcionar para mí en mis pruebas limitadas. –

+0

Gracias por el enlace mac OS X, esto hace que el manejo sea muy irregular, ya que funciona solo para los tipos sse (flotante y doble) pero no para el doble largo, que es específico para x87. Además, habilitar excepciones lo hace para todo el proceso, no para el hilo actual, lo que dificulta el trabajo con él. – nraynaud

0

No estoy seguro de cuál es el estándar, pero puedo decirte lo que he visto por experiencia, ya que puede ser útil. He codificado en C++ y los de NaN son a veces mi peor pesadilla. Aparecen en silencio y se propagan a través del cómputo hasta el final, hasta que tengo salida inútil. A menudo tuve que crear código adicional para detectar específicamente las circunstancias que causan NaN. Estoy usando Visual C++ 2008, así que espero que siga el estándar IEEE de esta manera.

+0

sí, es totalmente estándar. Pero el estándar define 3 niveles de uso 1) propagación de NaN e infs 2) indicadores, puede verificar 3) trampas de software. Tal vez su uso sea demasiado avanzado para mantener el comportamiento predeterminado. – nraynaud

0

El lenguaje de programación de Maple tiene un modelo numérico que respeta IEEE-754 y le permite configurar sus propios manipuladores de trampa, si lo desea. Estos son algunos enlaces:

Un raro La propiedad de Maple es que los números de coma flotante predeterminados son decimales (no binarios) y de precisión arbitraria. Si desea tratar con números de coma flotante binarios de 64 bits, envuélvalos en HFloat. Por ejemplo, 0.2 representa el número decimal exactamente, mientras que HFloat(0.2) representa el mismo número se obtendría mediante la asignación de 0,2 a un doble en C. Esto es evidente mediante la ejecución, por ejemplo,

a := HFloat(0.2); 
b := 0.2; 
evalf[20](a - b); 

Este calcula la diferencia entre a y b usando una aritmética de 20 dígitos decimales, y el resultado es 0.11E-16.

Cuestiones relacionadas