Why does this code get floating point exception when there is no float data-type?
Asked Answered
T

1

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
Terhune answered 11/7, 2018 at 22:14 Comment(21)
floating point execption is when you attempt a division or modulo by 0. it isn't exclusive to floating pointsPersas
How long does it take to reproduce the problem? When I run your code it just keeps running.Emmer
Use your debugger. Watch the value of deno and see if it ever is zero.Punchboard
@Emmer It works perfectly on hackerrank.com Passed Test cases took less than a secTerhune
What values are you putting in? I'm not getting the errorHamstring
@Easton Bornemeier hidden test case! This works fine for 2 test cases but produces floating point exception for rest twoTerhune
@TotallyNoob, In this case, it would be helpful to provide a link to the original problem.Emmer
hackerrank.com/contests/projecteuler/challenges/euler025/…Terhune
I was unable to edit the question this is the problem statementTerhune
Your code seem exactly runnable without exception. Did you debug your code step by step?Dread
@Yılmazedis debugging doesn't easily help if you don't know the input that leads tot he problem.Roseberry
@scohe001 Even after C++98 std::pow() only works with floating point numbers.Paracasein
@Yılmazedis Yes I tried to print values of deno and as much as I can think of deno never became zero hence floating point exception is a bit confusing in this case.Terhune
@FeiXiang Ahh looking closer at (7) it seems you're right. I skimmed and didn't look too closely at what Arithmetic1 was thinking it'd handle intUltramarine
input case for floating point exception: 1 50Roseberry
@Roseberry Yes, you are right.Dread
@Roseberry thanks! I have edited the question and put the error message for better understandingTerhune
Do you realize that an unsigned long long can only go up about 19 digits while the problem requires 5000? Even a long double can only go up to 308 digits (with floating point error, of course). You're going to need a new approach.Paracasein
This is simply triggering overflowHamstring
@FeiXiang Thank you so much! I'm going to change the approach.Terhune
The de-facto standard is gmplib.orgSabin
I
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.

Ironworks answered 11/7, 2018 at 22:31 Comment(6)
Thank you, but how should I change my code to overcome this problem?Terhune
Thank you for looking deep into the problem and helping me outTerhune
yes, just checked for 1 50 deno is 0. On Visual Studio however is 9223372036854775808. This is indeed UB.Roseberry
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.Copilot
with n>=19 the logic is ill-formed on a wide range of platforms. it just overflows the 64 bit boundries of long long.Granddaughter
Mildly related: You can use the "Russian peasant algorithm":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.Artois

© 2022 - 2024 — McMap. All rights reserved.