SIGFPE, арифметическое исключение с четко определенным разделением

#c #sigfpe

#c #sigfpe

Вопрос:

У меня есть следующий фрагмент кода c :

 void update(const int step, const int total) const
{
   double s = static_cast<double>(step);

   double t = static_cast<double>(total);

   std::cout << s/t <<"------n";

   // etc...
}
  

Я использую компилятор Intel c с активированным флагом -fp-trap=all . При запуске кода через gdb я получаю следующую ошибку:

 Program received signal SIGFPE, Arithmetic exception.
0x000000000040ee07 in NilDa::progressBar::update (this=0x7fffffffbc9c, step=1, total=60000) at /home/d2d/dev/NilDa/sources/utils/progressBar.h:69
69  std::cout << s/t <<"------n";
  

Я действительно не понимаю, что происходит. Разделение кажется четко определенным.

Комментарии:

1. входные данные: step = 1, total = 60000 (как сообщает gdb), поэтому s = 1.0, t = 60000.0

2. Кроме того, мы понятия не имеем, когда и где вызывается этот код. Как насчет простой main программы, которая просто делит 1.0 на 60000.0, чтобы посмотреть, есть ли что-то не так в этом простом случае.

3. @cigien Значения видны в выводе gdb 😉 Данте: Какой компилятор вы используете?

4. PS Если вы используете компилятор Intel C , быстрый поиск здесь решит ваш вопрос ( Enables or disables the IEEE trap for invalid operation. ): software.intel.com/content/www/us/en/develop/documentation /…

Ответ №1:

Я предполагаю, что вы используете компилятор Intel C (я не знаю ни одного другого компилятора, имеющего такой флаг). Если это так, вы можете посмотреть здесь: https://software.intel.com/content/www/us/en/develop/documentation/cpp-compiler-developer-guide-and-reference/top/compiler-reference/compiler-options/compiler-option-details/floating-point-options/fp-trap-qfp-trap.html#

Как указано в этой документации, аргумент all наследует ловушку для неточных результатов ( [no]inexact )

Включает или отключает ловушку IEEE для неточного результата.

Поскольку 1/60000 не может быть представлено числом с плавающей запятой, результат является неточным (1.66667e-05).

Комментарии:

1. @WolvernDEV Как указано в вопросе, я использую компилятор Intel c . Я понимаю точку зрения о приближении 1/6000, но верно ли это и для double? Я использую не число с плавающей запятой, а значение double .

2. Ну, независимо от двойного числа с плавающей точкой или чего-то еще, 1/60000 является периодическим результатом (1/6 * 1e-5). 1/6 не может быть представлено в виде числа с плавающей запятой или числа с фиксированной запятой 😉