7

I'm not dividing by zero and there is no float datatype in my code, I still get floating point exception.

#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;
}

All the previous questions on the same had the similar problem of dividing by Zero but variable deno can never be zero as n>=2.

Previous research from my side:

  1. “Floating point exception” in code that contains no floats
  2. Floating Point Exception C++ Why and what is it?

Problem statement: https://www.hackerrank.com/contests/projecteuler/challenges/euler025/problem

It passes 2 test cases and fails 2. All are hidden test cases. Result image

On passing the input 1 50 we can reproduce the error. Details:

 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
Breakpoint
  • 428
  • 6
  • 19

1 Answers1

9

It is perfectly normal for integer division to produce an exception that is reported as "floating point exception" on some platforms (Linux, for one example). You can easily get it from integer division by zero, or, for another example, by triggering overflow as in

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

http://coliru.stacked-crooked.com/a/07c5fdf47278b696

In certain contexts this exception might appear or disappear depending on optimization levels. The exception is normally only triggered when the compiler decided to generate the actual division instruction (as opposed to optimizing out the division).


In your case unsigned integer division is used, so division by zero seems to be the only possible culprit. I would guess that this

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

happens to result in zero in deno. pow is a floating-point function that produces a floating-point result. Conversion from floating-point type to integer type leads to undefined behavior if the original value is too large (which is the case for n equal to 50). Note that this is the case even if the target integer type is unsigned.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • 1
    Thank you, but how should I change my code to overcome this problem? – Breakpoint Jul 11 '18 at 22:42
  • Thank you for looking deep into the problem and helping me out – Breakpoint Jul 11 '18 at 22:54
  • yes, just checked for `1 50` `deno` is `0`. On Visual Studio however is `9223372036854775808`. This is indeed UB. – bolov Jul 11 '18 at 22:55
  • 1
    Write your own pow() function. `std::pow` always converts ints and returns floating point results. There is no equivalent for ints only in the standard library. There are numerous int equivalents on the web. – doug Jul 12 '18 at 05:44
  • with n>=19 the logic is ill-formed on a wide range of platforms. it just overflows the 64 bit boundries of long long. – Red.Wave Jul 12 '18 at 09:37
  • Mildly related: You can use the "Russian peasant algorithm":http://lafstern.org/matt/col3.pdf for efficient integer exponentiation. It is based on an ancient approach of _strength reduction_ of multiplication to addition/subtraction/comparison. In this case, it reduces operation strength from exponentiation to at most multiplication. – Arne Vogel Jul 16 '18 at 09:56