Search code examples
c++abort

C++ Abort() has been called when I input extremely long string to get substring


https://www.hackerrank.com/challenges/sam-and-substrings/problem

This is the problem I'm working on it and I have a problem.

Here is my code

#include <string>
#include <iostream>
#include <vector>
double const modulo = 1000000007;

int main()
{
    std::string n("");
    std::cin >> n;
    long sum(0);
    std::vector<std::string> newlyAddedSubstring;

    for (auto i : n)
    {
        for (auto &j : newlyAddedSubstring)
        {
            j += i;
            long d = std::fmod(std::stod(j), modulo);
            sum = std::fmod(sum + d, modulo);
        }
        newlyAddedSubstring.push_back(std::string(1, i)); 
        newlyAddedSubstring.back();
        sum = std::fmod(sum + (i - '0'), modulo);
    }
    std::cout << sum << std::endl;
}

This is a part of input and input is actually 1003 size long 630078954945407486971302572117011329116721271139829179349572383637541443562605787816061110360853600744212572072073871985233228681677019488795915592613136558538697419369158961413804139004860949683711756764106408843746324318507090...

It has no problem until around 327 repetition(i.e size of newlyAddedSubstring is around 327) but it got problem on

long d = std::fmod(std::stod(j), modulo);

Any comments or feedback would be greatly appreciated!!


Solution

  • std::stod throws the exception std::out_of_range if the value that it parsed from the string it outside the range of values that double can hold.

    The largest value that a typical double implementation can hold is roughly 300 digits long. Your number is larger than that.

    The exception is therefore thrown and because you don't catch it std::terminate is called, which by default calls std::abort, terminating the program.

    You cannot store such a large number in a double. You can try std::stold instead, which tries to parse the number as long double, which may be larger than double and may be able to hold your value.

    Also, in general, floating-point values are not able to represent integers exactly. Therefore it is pretty pointless to do the modulo operation on the double or long double as you are doing. It will not give an exact result and for very large values will essentially generate random values.

    If you want to do exact modulo on such a large integer, you need an arbitrary-size integer library or you need to implement the modulo operation yourself.