Почему этот код получает исключение с плавающей запятой, когда отсутствует тип данных с плавающей запятой?

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

#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;


int main() {
    unsigned long long int t,n;

    cin>>t;
    while(t--)
    {
        cin>>n;
        unsigned long long int deno = pow(10,n-1),count=2,sum = 0,f1=1,f2=1;

         while(1){
            sum = f1+f2;
            f1 = f2;
            f2 = sum;
            count++;
            if((int)(sum/deno)>0){
                cout<<count<<endl;
                 break;
             } 
        }

    }
    return 0;
}

Все предыдущие вопросы по одному и тому же имели аналогичную проблему деления на ноль, но переменная deno никогда не может быть равна нулю, так как n>=2,

Предыдущее исследование с моей стороны:

  1. "Исключение с плавающей точкой" в коде, который не содержит чисел с плавающей точкой
  2. Исключение с плавающей точкой C++ Почему и что это?

Постановка проблемы: https://www.hackerrank.com/contests/projecteuler/challenges/euler025/problem

Он проходит 2 контрольных теста и не проходит 2. Все они являются скрытыми Изображение результата

Пройдя ввод 1 50, мы можем воспроизвести ошибку. Подробности:

 GDB trace: Reading symbols from solution...done. [New LWP 15127] Core
 was generated by `solution'. Program terminated with signal SIGFPE,
 Arithmetic exception.
 #0  main () at solution.cc:23 
 23 if((int)(sum/deno)>0){
 #0  main () at solution.cc:23

1 ответ

Решение

Целочисленное деление совершенно нормально для создания исключения, которое сообщается как "исключение с плавающей запятой" на некоторых платформах (например, Linux). Вы можете легко получить его из целочисленного деления на ноль или, например, запустив переполнение, как в

int i = INT_MIN;
int b = -1;
i = i / b;

/questions/25655018/preobrazovat-desyatichnuyu-v-dvojnuyu/25655034#25655034

В определенных контекстах это исключение может появляться или исчезать в зависимости от уровней оптимизации. Исключение обычно срабатывает только тогда, когда компилятор решил сгенерировать фактическую инструкцию деления (в отличие от оптимизации деления).


В вашем случае используется целочисленное деление без знака, так что деление на ноль кажется единственно возможным виновником. Я предполагаю, что это

unsigned long long int deno = pow(10,n-1);

случается, приводит к нулю в deno, pow является функцией с плавающей точкой, которая производит результат с плавающей точкой. Преобразование из типа с плавающей точкой в ​​целочисленный тип приводит к неопределенному поведению, если исходное значение слишком велико (что имеет место для n равно 50). Обратите внимание, что это имеет место, даже если целевой тип целого числа без знака.

Другие вопросы по тегам