Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Program abruptly ends after cin

Tags:

c++

I am writing code to get the last digit of very large fibonacci numbers such as fib(239), etc.. I am using strings to store the numbers, grabbing the individual chars from end to beginning and then converting them to int and than storing the values back into another string. I have not been able to test what I have written because my program keeps abruptly closing after the std::cin >> n; line. Here is what I have so far.

#include <iostream>
#include <string>
using std::cin;
using std::cout;
using namespace std; 

char get_fibonacci_last_digit_naive(int n) {
cout << "in func";
if (n <= 1)
    return (char)n;

string previous= "0";
string current= "1";

for (int i = 0; i < n - 1; ++i) {
    //long long tmp_previous = previous;
    string tmp_previous= previous; 

    previous = current;

    //current = tmp_previous + current; // could also use previous instead of current
    // for with the current length of the longest of the two strings
    //iterates from the end of the string to the front
    for (int j=current.length(); j>=0; --j) {
        // grab consectutive positions in the strings & convert them to integers
        int t;
        if (tmp_previous.at(j) == '\0') 
            // tmp_previous is empty use 0 instead
            t=0;  
        else
            t = stoi((string&)(tmp_previous.at(j))); 
        int c = stoi((string&)(current.at(j)));
        // add the integers together
        int valueAtJ= t+c;
        // store the value into the equivalent position in current
        current.at(j) = (char)(valueAtJ); 
    }
    cout << current << ":current value"; 
}

return current[current.length()-1];
}

int main() {
int n;
std::cin >> n;

//char& c = get_fibonacci_last_digit_naive(n);  // reference to a local variable returned WARNING
// http://stackoverflow.com/questions/4643713/c-returning-reference-to-local-variable
cout << "before call";
char c = get_fibonacci_last_digit_naive(n);
std::cout << c << '\n';

return 0;
}

The output is consistently the same. No matter what I enter for n, the output is always the same. This is the line I used to run the code and its output.

$ g++ -pipe -O2 -std=c++14 fibonacci_last_digit.cpp -lm

$ ./a.exe
10

There is a newline after the 10 and the 10 is what I input for n. I appreciate any help. And happy holidays!

like image 699
noc_coder Avatar asked Jan 05 '23 20:01

noc_coder


1 Answers

I'm posting this because your understanding of the problem seems to be taking a backseat to the choice of solution you're attempting to deploy. This is an example of an XY Problem, a problem where the choice of solution method and problems or roadblocks with its implementation obfuscates the actual problem you're trying to solve.

You are trying to calculate the final digit of the Nth Fibonacci number, where N could be gregarious. The basic understanding of the fibonacci sequence tells you that

fib(0) = 0 
fib(1) = 1 
fib(n) = fib(n-1) + fib(n-2), for all n larger than 1.

The iterative solution to solving fib(N) for its value would be:

unsigned fib(unsigned n)
{
    if (n <= 1)
        return n;

    unsigned previous = 0;
    unsigned current = 1;
    for (int i=1; i<n; ++i)
    {
        unsigned value = previous + current;
        previous = current;
        current = value;
    }
    return current;
}

which is all well and good, but will obviously overflow once N causes an overflow of the storage capabilities of our chosen data type (in the above case, unsigned on most 32bit platforms will overflow after a mere 47 iterations).

But we don't need the actual fib values for each iteration. We only need the last digit of each iteration. Well, the base-10 last-digit is easy enough to get from any unsigned value. For our example, simply replace this:

current = value;

with this:

current = value % 10;

giving us a near-identical algorithm, but one that only "remembers" the last digit on each iteration:

unsigned fib_last_digit(unsigned n)
{
    if (n <= 1)
        return n;

    unsigned previous = 0;
    unsigned current = 1;
    for (int i=1; i<n; ++i)
    {
        unsigned value = previous + current;
        previous = current;
        current = value % 10; // HERE
    }
    return current;
}

Now current always holds the single last digit of the prior sum, whether that prior sum exceeded 10 or not really isn't relevant to us. Once we have that the next iteration can use it to calculate the sum of two single positive digits, which cannot exceed 18, and again, we only need the last digit from that for the next iteration, etc.. This continues until we iterate however many times requested, and when finished, the final answer will present itself.

Validation

We know the first 20 or so fibonacci numbers look like this, run through fib:

0:0
1:1
2:1
3:2
4:3
5:5
6:8
7:13
8:21
9:34
10:55
11:89
12:144
13:233
14:377
15:610
16:987
17:1597
18:2584
19:4181
20:6765

Here's what we get when we run the algorithm through fib_last_digit instead:

0:0
1:1
2:1
3:2
4:3
5:5
6:8
7:3
8:1
9:4
10:5
11:9
12:4
13:3
14:7
15:0
16:7
17:7
18:4
19:1
20:5

That should give you a budding sense of confidence this is likely the algorithm you seek, and you can forego the string manipulations entirely.

like image 114
WhozCraig Avatar answered Jan 30 '23 04:01

WhozCraig