2010-09-01 2 views
28

Я собираюсь выполнить математические вычисления с использованием C++. Номер с плавающей запятой ввода является допустимым числом, но после вычислений полученное значение является NaN. Я хотел бы проследить точку, в которой появляется значение NaN (возможно, с использованием GDB), вместо того, чтобы вставлять в код много isNan(). Но я обнаружил, что даже такой код не вызывает исключение, когда появляется значение NaN.Как проследить NaN в C++

double dirty = 0.0; 
double nanvalue = 0.0/dirty; 

Может ли кто-нибудь предложить метод отслеживания NaN или превращения NaN в исключение?

+0

Связанный: [Могу ли я заставить gcc сказать мне, когда результаты вычислений в NaN или inf во время выполнения?] (Http://stackoverflow.com/questions/2941611/can-i-make-gcc-tell-me-when -a-calculate-results-in-nan-or-inf-at-runtime/20973509) – legends2k

+0

Также http://stackoverflow.com/questions/5393997/stopping-the-debugger-when-a-nan-floating-point -number-is-production – Riot

ответ

7

В Visual Studio можно использовать функцию _controlfp, чтобы установить поведение вычислений с плавающей точкой (см. http://msdn.microsoft.com/en-us/library/e9b52ceh(VS.80).aspx). Возможно, для вашей платформы есть аналогичный вариант.

+0

Привет, спасибо за ваш ответ. К сожалению, моя платформа GCC4.1, Centos 5.5 Linux. Я все еще пытаюсь понять, как добиться того же самого в Linux с помощью GCC – user1492900

+2

feenableexcept() кажется работающим, теперь я пытаюсь проследить свою программу с этим. http://gcc.gnu.org/onlinedocs/gcc-3.1.1/g77/Floating-point-Exception-Handling.html # Floating-point% 20Exception% 20Handling – user1492900

0

Можно включить так называемую «сигнализацию NaN». Это должно сделать так, чтобы отладчик мог найти правильную позицию.

Via гугле, я нашел это для включения сигнализации пренебрежимо малых в C++, ни одна идея, если она не работает:

std::numeric_limits::signaling_NaN();

Usefulness of signaling NaN?

+2

Это выражение оценивается сигнальным NaN, но я думаю, что pagedown больше интересуется форсированием исключения с плавающей запятой для операций, возвращающих NaN, что, вероятно, будет параметром компилятора для конкретной платформы или конфигурацией времени выполнения FP-процессор. –

+0

Ах, извините. Я понял, что это делает все сигналы NaN. –

+0

Большое спасибо. Моя платформа GCC4.1, Centos 5.5 Linux Я собираюсь взглянуть на параметры компилятора :) – user1492900

35

Поскольку вы упоминаете с помощью GDB, вот решение, которое работает с GCC - вы хотите функции, определенной в fenv.h:

#include <fenv.h> 
#include <stdio.h> 

int main(int argc, char **argv) 
{ 
    double dirty = 0.0; 

    feenableexcept(FE_ALL_EXCEPT & ~FE_INEXACT); // Enable all floating point exceptions but FE_INEXACT 
    double nanval=0.0/dirty; 
    printf("Succeeded! dirty=%lf, nanval=%lf\n",dirty,nanval); 
} 

Running выше программа производит вывод «Floating исключения точки». Без звонок в feenableexcept, «Преемник!» сообщение печатается.

Если вы должны были написать обработчик сигнала для SIGFPE, это может быть хорошим местом для установить точку останова и получить нужную трассировку. (Отказ от ответственности: не пробовал!)

+0

Большое спасибо – user1492900

+2

Ошибка найдена :) – user1492900

+13

Спасибо за этот ответ, я просто хочу указать, что включение * всех * исключений с плавающей запятой позволяет также FE_INEXACT, что происходит очень часто (даже для: float f = 0,1), и отладка становится невозможной. Лучше использовать feenableexcept (FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW); – DarioP

1

Некоторые примечания о программировании с плавающей запятой можно найти на http://ds9a.nl/fp/, включая разницу между 1/0 и 1.0/0 и т. Д., А также то, что такое NaN и как оно действует.

+0

Большое спасибо – user1492900

Смежные вопросы