Xcode gives different results every time I run C++ tests - c++

I am working on a program that receives a char array. In that char array are numbers separated by spaces. The program is supposed to receive a number and add that number's palindrome to itself. If the result is not a palindrome, then we are supposed to add the result's palindrome to the result and so on until a result is a palindrome. For example, if the char array is "195", then 195 + 591 = 786. 786 is not a palindrome, so 786 + 687 = 1473. 1473 + 3741 = 5214. Finally 5214 + 4125 = 9339, which is a palindrome, so this is the answer. Then, the program should return the number of additions it ran to get the answer, followed by the answer. In this example, the program would return "4 9339".
My program works (as far as I can tell,) but for whatever reason, whenever I run Xcode, it returns different results. For example, one time I ran it everything was fine except for case 7. The next time I ran it, every single test failed. If I ran it again, every case would work except for 7 and 9. Does anybody know why this is happening? Below is all of my code, including the test cases that Xcode is running. I also tried commenting what is occurring in the program.
I would appreciate anybody's help! I am an amateur when it comes to C++, so it might be something trivial I am overlooking, or it could be something more advanced--I'm honestly not really sure. Thank you to everybody in advance!
EDIT: I have used Xcode's debugger and nothing fails or looks out of place when I do it that way, which makes it only more mysterious as to why it fails when I run the tests without debugging.
EDIT 2: Then test cases were provided by my professor, not myself.
#include <iostream>
#include <string>
using namespace std;
//returns the reverse of a number
unsigned long reverse(unsigned long n) {
unsigned long reverse = 0;
while(n != 0) {
unsigned long remainder = n%10;
reverse = reverse*10 + remainder;
n /= 10;
}
return reverse;
}
//return what the palindrome result is
string palindrome(string numberInString, int &counter) {
counter++;
//convert input, which is a string, to int
unsigned long number = std::stol(numberInString);
//reverse number and assign it to numberReversed
unsigned long numberReversed = reverse(number);
//add the number and its reverse
unsigned long result = number + numberReversed;
//reverse the result and assign it to resultReversed
unsigned long resultReversed = reverse(result);
//check to see if result and its reverse are equal; otherwise, keep going until they are
while (result != resultReversed) {
counter++;
//reassign number as result
number = result;
//reverse number and assign it to numberReversed
numberReversed = reverse(number);
//add the number and its reverse
result = number + numberReversed;
//reverse the result and assign it to resultReversed
resultReversed = reverse(result);
}
//return result
return std::to_string(result);
}
//the "main" method
char* find(const char* array) {
//instatntite counter, which will be used later
int counter = 0;
//instantiate result string, which is what we are returning
string result = "";
int i = 0;
//will be used to construct int being checked as a palindrome
string currentNumberConstruction = "";
//go through array until end of array
while (array[i] != '\0') {
//if find a space
if (array[i] == ' ') {
//call palindrome function and add it to result later on
string palindromeNumber = palindrome(currentNumberConstruction, counter);
result += std::to_string(counter);
//add to result how many cycles until palindrome found
result += " " + palindromeNumber + " ";
//reset counter (how many cycles until palindrome found)
counter = 0;
//reset currentNumberConstruction (int being checked as a palindrome)
currentNumberConstruction = "";
//continue through array
i++;
} else {
//add char checked to currentNumberConstruction (int being checked as a palindrome)
currentNumberConstruction += array[i];
//continue through array
i++;
}
}
if (currentNumberConstruction != "") {
string palindromeNumber = palindrome(currentNumberConstruction, counter);
result += std::to_string(counter);
result += " " + palindromeNumber;
counter = 0;
currentNumberConstruction = "";
i++;
}
//convert result from string to char*
char* realResult = new char[result.length()];
for (unsigned int j = 0; j < result.length(); j++) {
realResult[j] = result[j];
}
//return char* realResult
return realResult;
}
int main() {
const char* array = NULL;
const char* expected = 0;
for (int i = 0; i < 10; i++) {
switch (i) {
case 0:
array = "195 265 750";
expected = "4 9339 5 45254 3 6666";
break;
case 1:
array = "2 99 4000000000 20 100 1";
expected = "1 4 6 79497 1 4000000004 1 22 1 101 1 2";
break;
case 2:
array = "79 88 97 99";
expected = "6 44044 6 44044 6 44044 6 79497";
break;
case 3:
array = "157 158 166 167 175 188 193 197";
expected = "3 8888 3 11011 5 45254 11 88555588 4 9559 7 233332 8 233332 7 881188";
break;
case 4:
array = "266 273 274 292 365";
expected = "11 88555588 4 5115 4 9559 8 233332 11 88555588";
break;
case 5:
array = "1089 1091 1099";
expected = "4 79497 1 2992 2 11011";
break;
case 6:
array = "19991 2914560 12345678";
expected = "8 16699661 5 47977974 1 99999999";
break;
case 7:
array = "777";
expected = "4 23232";
break;
case 8:
array = "130031 9";
expected = "1 260062 2 99";
break;
case 9:
array = "1234567890123456789";
expected = "2 12222222211222222221";
break;
default:
cout << "we should never get here" << endl;
return -1;
}
char* actual = find(array);
bool equal = strcmp(expected, actual) == 0;
cout << "test " << (i + 1) << ": " << (equal ? "ok" : "failed");
if (!equal) {
cout << " expected [" << expected << "] but was [" << actual << "]";
}
cout << endl;
delete actual;
}
return EXIT_SUCCESS;
}

Your problem is here:
char* array = NULL;
You don't actually allocate any memory to store the array, you need to initialize this in a way that gives it some memory. Otherwise you are just picking random memory in the system and you will probably get a SegFault eventually.
This could be done like this:
char array[100];
or you could use std::string instead. This creates a character array with 100 characters to use, you can adjust the size to your need.

Not sure if it's the only mistake but you don't null terminate result:
char* realResult = new char[result.length()];
Should be:
char* realResult = new char[result.length()+1];
realResult [result.length()] = 0;
Otherwise the behaviour could be very random.

Related

my value is more than the range of unsigned integer

i have this exercise:" consider some natural number n, if it is not a Palindrom number, change the order of the digits in reverse order and add the resulting number with the original number. If the sum is not a palindrom number, repeat the same procedure on that sum until a palindrom number is obtained. Whether the above process is finite for any n. If yes, print out the number of process "
ex
input:1 output: 0
input: 12 output: 1
my problem is when i encounter larger number such as 19170 it will be over the limit of unsigned long long int
It will also be great if anyone can explain or guide me to resources that can help me understand it further.
#include <iostream>
#include <math.h>
using namespace std;
bool check (long long int n)
{
long long int clone_n=n,count=0,ans=0;
while (clone_n!=0)
{
clone_n/=10;
count++;
}
clone_n=n;
for(int i=count;i>=0;i--)
{
ans+=(clone_n%10)*pow(10,i-1);
clone_n/=10;
}
if(ans==n)
{
return true;
}
return false;
}
long long int reverse(long long int n)
{
long long int clone_n=n,count=0,ans=0;
while (clone_n!=0)
{
clone_n/=10;
count++;
}
clone_n=n;
for(int i=count;i>=0;i--)
{
ans+=(clone_n%10)*pow(10,i-1);
clone_n/=10;
}
return ans;
}
int main()
{
long long int n,count=0;
cin>>n;
if(check(n))
{
cout<<0;
return 0;
}
else
{
while(check(n)!=1)
{
count++;
n+=reverse(n);
}
}
cout<<count;
}
my code is also included in the link: https://ideone.com/0p7JJU
The natural number that will not terminate the algorithm that the OP describe is called Lychrel number. https://en.wikipedia.org/wiki/Lychrel_number
It is currently unknown if any of these number exists, as correctly guessed by zkoza in the above answer, 196 is the smallest candidate to be a Lychrel number.
So, this is a specifically hard problem to tackle, however, I would like to address the specific overflow issue that the OP is facing. As pointed out by largest_prime_is_463035818 in the comments, there is no actual needs of any integer representation.
#include <iostream>
//take advantage of the fact that std::string use contiguous memory
bool is_palindrome(const char* first, const char* last)
{
--last;
while(first < last) {
if (*first != *last)
return false;
++first;
--last;
}
return true;
}
std::string reverse_and_add(const std::string& digits)
{
size_t size = digits.size();
//the result string will be at least the same length
std::string result(size,'0');
int carry_over = 0;
int ascii_zero = 48;
for (size_t i = 0; i < size; i++)
{
int front = digits.at(i) - ascii_zero;
int back = digits.at(size - i - 1) - ascii_zero;
int sum = front + back + carry_over;
carry_over = sum / 10;
int digit = sum >= 10 ? sum - 10 : sum;
result[size - i - 1] = static_cast<char>(digit + ascii_zero);
}
//if at the last step we have a carry over we need to add an extra digit to
//the string
if (carry_over > 0)
result = static_cast<char>(carry_over + ascii_zero) + result;
return result;
}
void check(const std::string& s, int max_iteration)
{
int counter = 0;
std::string v(s);
while(!is_palindrome(v.c_str(), v.c_str() + v.size()) && counter < max_iteration)
{
v = reverse_and_add(v);
if (counter % 1000 == 0 && counter > 0)
std::cout << "progressing iteration: " << counter << " string size: " << v.size() << std::endl;
counter++;
}
if (counter == max_iteration)
std::cout << "No result found" << std::endl;
else
std::cout << "result: " << counter << std::endl;
}
int main()
{
int max_iteration = 50000;
check("187",max_iteration); // -> return 23
check("19170", max_iteration); // -> doesn't find a solution
// the final string is thousands of characters
}
UPDATE
Just for fun, I run 196 till 1000000 digits (that it took 3 years to complete 1987) and it produce the same result in about an hour and half (these hardware engineers are amazing).
result: 2415836
./a.out 5315.83s user 21.29s system 99% cpu 1:29:12.58 total
I assume this is a homework question.
The first number for which the sequence does not seem to be finite is as small as 196. I terminated a program after it hit 300000 digits.
What can you do?
Write a similar program where you implement your own "big numbers". It's an easy task, because all you need is addition of two same-length numbers, reversal, checking for being a palindrom, perhaps printing. You can use std::vector or std::string.
Then, introduce an ad hoc threshold, like 100 or 1000 iterations. If the sequence will reach the threshold, stop it and return false.
It is possible that you did not present here the complete, detailed description of the problem. I found a similar problem on the internet, but with an explicit threshold of 5 iterations. Or perhaps it is a problem that you've invented yourself, unaware of its complexity? Or the teacher is pulling your leg? Or I made a mistake in my code.
A famous example of a problem that has a simple formulation but no known solution is the Collatz conjecture, https://en.wikipedia.org/wiki/Collatz_conjecture . It can't be ruled out that your problem is of a similar type.
Here, for reference, is my solution for numbers from 180 to 195 (the first number in the sequence, the number of iteration, the last number in the sequence)
180 3 747
181 0 181
182 6 45254
183 4 13431
184 3 2552
185 3 4774
186 3 6996
187 23 8813200023188
188 7 233332
189 2 1881
190 7 45254
191 0 191
192 4 6996
193 8 233332
194 3 2992
195 4 9339
Instead of numeric data type you can use string to store the values and do addition by parsing the whole string like this
#include <iostream>
#include <string>
int main()
{
std::string s1 = "759579537575937593759387";
std::string s2 = "9956775659653876536535637653";
int n1=s1.size()-1,n2=s2.size()-1;
std::string s3 = "";
uint8_t carry = 0;
while(n1>=0 && n2>=0){
uint8_t num1 = (int)s1[n1--] - 48;
uint8_t num2 = (int)s2[n2--] - 48;
uint8_t sum = char(num1+num2) + carry;
carry = sum/10; // to get carry
sum = sum%10;
s3.insert(0,1,char(sum+48));
}
while(n1>=0)
{
uint8_t sum = carry + (int)s1[n1--] - 48;
carry = sum/10;
sum = sum%10;
s3.insert(0,1,char(sum+48));
}
while(n2>=0)
{
uint8_t sum = carry + (int)s2[n2--] - 48;
carry = sum/10;
sum = sum%10;
s3.insert(0,1,char(sum+48));
}
if (carry)
s3.insert(0,1,char(carry+48));
std::cout<<s3<<std::endl;
}
also you check if they are palindromic or not using two pointer method.
The above sum which I get is 9957535239191452474129397040, there is no limit to addition by this method

Converting MQL4 to C++?

I would like to convert a bunch of stock/forex indicators written in MQL4 (.mq4 files) to C++. Previously, I had only been programming in Python and had very little exposure to both MQL4 and C++. Furthermore, I am not at all aware of the ways to go about such a problem, and whether it is even feasible. (Although, worst case scenario, manually recoding them all should definitely be feasible.)
I took a simple indicator, the Simple Moving Average, as an example and started tinkering with it and running it using a C++ compiler. Knowing that the syntax of the two languages is highly similar, I thought this could be a relatively easy process, and even automable to some degree.
Here is the Simple Moving Average script extracted from the .mq4 file available at this link:
MA_Period=5;
void sma()
{
double sum=0;
int i,pos=Bars-ExtCountedBars-1;
//---- initial accumulation
if(pos<MA_Period) pos=MA_Period;
for(i=1;i<MA_Period;i++,pos--)
sum+=Close[pos];
//---- main calculation loop
while(pos>=0)
{
sum+=Close[pos];
ExtMapBuffer[pos]=sum/MA_Period;
sum-=Close[pos+MA_Period-1];
pos--;
}
//---- zero initial bars
if(ExtCountedBars<1)
for(i=1;i<MA_Period;i++) ExtMapBuffer[Bars-i]=0;
}
And here is my C++ implementation, at the moment testing it on a short array arr[] representing the Close array in MQL4. Furthermore, I dropped MQL4's Bars and ExtCountedBars variables (as I want to run the indicator on static, historical data), and replaced ExtMapBuffer with an array called output[], with equal length as the "price" array arr[].
#include <iostream>
using namespace std;
int main()
{
int MA_Period=5;
int arr[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
double sum=0;
int i, pos=0;
int output[20];
cout << "Pos: " << pos << endl;
//---- initial accumulation
if(pos<MA_Period) pos=MA_Period;
for(i=1;i<MA_Period;i++,pos--)
sum+=arr[pos];
cout << "Sum of past " << MA_Period << " prices : " << sum << endl;
cout << "Pos = " << pos << endl;
//---- main calculation loop
while(pos>=0)
{
sum+=arr[pos];
output[pos]=sum/MA_Period;
sum-=arr[pos+MA_Period-1];
pos--;
}
for(int j=0;j<sizeof(output)/sizeof(output[0]);j++){
cout << "output[" << j << "] = " << output[j] << endl;
}
return 0;
}
The console output I'm gettign for the output array values are:
output[0] = 3
output[1] = 4
output[2] = 65535
output[3] = 1
output[4] = 1706671568
output[5] = 32766
output[6] = 4197523
output[7] = 0
output[8] = 2
output[9] = 0
output[10] = 4197613
output[11] = 0
output[12] = 124
output[13] = 0
output[14] = 0
output[15] = 0
output[16] = 4197536
output[17] = 0
output[18] = 4196352
output[19] = 0
which is clearly not correct. I tried retaining as much from the original MQL4 code when converting to C++ but now hit a roadblock as to why the output is massively different from the expected:
output[0] = nan
output[1] = nan
output[2] = nan
output[3] = nan
output[4] = 3
output[5] = 4
output[6] = 5
output[7] = 6
output[8] = 7
output[9] = 8
output[10] = 9
output[11] = 10
output[12] = 11
output[13] = 12
output[14] = 13
output[15] = 14
output[16] = 15
output[17] = 16
output[18] = 17
output[19] = 18
What am I missing / misunderstanding in the process of converting my MQL4 code to C++?
There are several problems with this code. The main issue is your use of indices i and pos. In particular, after the initial accumulation, pos is equal to 1, so the main calculation loop will only run one iteration before it is done. So only output[1] gets written to, the rest of the array is uninitialized, and may contain any value.
Also note that array indices in C start at zero. Your initial accumulation loop starts at 1, which is not what you want.
I would avoid having two variables for indices, and only use one. To initialize sum, write:
for (int i = 0; i < MA_Period; ++i) {
sum += arr[i];
output[i] = -1;
}
Then to do the remainder write:
for (int i = MA_Period; i < sizeof(output) / sizeof(output[0]); ++i) {
sum += arr[i];
sum -= arr[i - MA_Period];
output[i] = sum / MA_Period;
}
This will give you the expected output. Note that there is no way to get nan for the first 5 values, as an int can never be nan. If you make output an array of double it is possible though, for example using this line in the initial loop:
output[i] = 0.0 / 0.0;
As for why the original MQL4 code worked: it initializes pos to Bars - ExtCountedBars - 1, whereas you initialized it to 0 in your C++ version.

Program crashes and does not display correct output

So I am working on a very "basic" problem for my c++ class and have encountered some errors. The problem is this
An interesting problem in number theory is sometimes called the “necklace problem.” This problem begins with two single-digit numbers. The next number is obtained by adding the first two numbers together and saving only the ones-digit. This process is repeated until the “necklace” closes by returning to the original two numbers. For example, if the starting numbers are 1 and 8, twelve steps are required to close the “necklace”:
18976392134718
Write a program that asks the user for two starting numbers, and then displays the sequence and the number of steps taken. The program output should look similar to:
Enter first number: 1
Enter ssecond number: 8
18976392134718
Your numbers required 12 steps.
What I have done is this:
` #include <iostream>
using namespace std;
int necklace(){
int firstNumber, secondNumber, total = 0, counter = 10, sumOfTwo, tempOne, tempTwo, count;
// 2 single digit numbers
// add first two numbers and save only one digit
// process keeps going until original numbers are found
cout << "Enter the first number: \n";
cin >> firstNumber;
cout << "Enter the second number: \n";
cin >> secondNumber;
sumOfTwo = firstNumber + secondNumber;
while (sumOfTwo >= 10){
sumOfTwo /= 10;
}
int numbersArray[] = {firstNumber, secondNumber, sumOfTwo};
for(int i = 0; i <= 20; i++){
tempOne = numbersArray[i + 1];
tempTwo = numbersArray[i + 2];
sumOfTwo = tempOne + tempTwo;
while (sumOfTwo >= 10){
sumOfTwo %= 10;
}
numbersArray[i + 3] = sumOfTwo;
total++;
if(tempOne == firstNumber && tempTwo == secondNumber){
break;
}
}
for(int i = 0; i < sizeof(numbersArray); i++){
cout << numbersArray[i];
}
cout << endl << "It took " << total << " steps to finish. \n";
return total;
}
int main() {
necklace();
}
`
The problem I am getting is that it will print out all the numbers except the original 2, for example if I use the example with 1 and 8, it will print out 189763921347 and then crash, when it is supposed to print out 18976392134718 with the 1 and 8 at the end of it. Any suggestions? Thanks!
int numbersArray[] = {firstNumber, secondNumber, sumOfTwo};
with three elements on the right hand side makes it an array of size 3. Meaning with indexes 0, 1 and 2.
The use of higher indexes will result in Undefined Behaviour (UB).
On the other hand:
for(int i = 0; i <= 20; i++){
tempOne = numbersArray[i + 1];
tempTwo = numbersArray[i + 2];
[...]
numbersArray[i + 3] = sumOfTwo;
with i up to 20 (included) indexes this very same array from 0 to 23 for the last line!
Next:
for(int i = 0; i < sizeof(numbersArray); i++){
sizeof(numbersArray) returns the size in bytes of the array:
sizeof(numbersArray) = 3 * sizeof(int)
Higher than 3, the real size of the array.
But, if you intend to print the values but not store them, you don't need an array. You just need to "exchange" the values like:
one two // beginning of loop
___|
| __ new_digit
| |
v v
one two // end of loop

C++ Program abruptly ends after cin

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!
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.
Running this code on a Mac I get:
libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: basic_string before callin funcAbort trap: 6
The most obvious problem with the code itself is in the following line:
for (int j=current.length(); j>=0; --j) {
Reasons:
If you are doing things like current.at(j), this will crash immediately. For example, the string "blah" has length 4, but there is no character at position 4.
The length of tmp_previous may be different from current. Calling tmp_previous.at(j) will crash when you go from 8 to 13 for example.
Additionally, as others have pointed out, if the the only thing you're interested in is the last digit, you do not need to go through the trouble of looping through every digit of every number. The trick here is to only remember the last digit of previous and current, so large numbers are never a problem and you don't have to do things like stoi.
As an alternative to a previous answer would be the string addition.
I tested it with the fibonacci number of 100000 and it works fine in just a few seconds. Working only with the last digit solves your problem for even larger numbers for sure. for all of you requiring the fibonacci number as well, here an algorithm:
std::string str_add(std::string a, std::string b)
{
// http://ideone.com/o7wLTt
size_t n = max(a.size(), b.size());
if (n > a.size()) {
a = string(n-a.size(), '0') + a;
}
if (n > b.size()) {
b = string(n-b.size(), '0') + b;
}
string result(n + 1, '0');
char carry = 0;
std::transform(a.rbegin(), a.rend(), b.rbegin(), result.rbegin(), [&carry](char x, char y)
{
char z = (x - '0') + (y - '0') + carry;
if (z > 9) {
carry = 1;
z -= 10;
} else {
carry = 0;
}
return z + '0';
});
result[0] = carry + '0';
n = result.find_first_not_of("0");
if (n != string::npos) {
result = result.substr(n);
}
return result;
}
std::string str_fib(size_t i)
{
std::string n1 = "0";
std::string n2 = "1";
for (size_t idx = 0; idx < i; ++idx) {
const std::string f = str_add(n1, n2);
n1 = n2;
n2 = f;
}
return n1;
}
int main() {
const size_t i = 100000;
const std::string f = str_fib(i);
if (!f.empty()) {
std::cout << "fibonacci of " << i << " = " << f << " | last digit: " << f[f.size() - 1] << std::endl;
}
std::cin.sync(); std::cin.get();
return 0;
}
Try it with first calculating the fibonacci number and then converting the int to a std::string using std::to_string(). in the following you can extract the last digit using the [] operator on the last index.
int fib(int i)
{
int number = 1;
if (i > 2) {
number = fib(i - 1) + fib(i - 2);
}
return number;
}
int main() {
const int i = 10;
const int f = fib(i);
const std::string s = std::to_string(f);
if (!s.empty()) {
std::cout << "fibonacci of " << i << " = " << f << " | last digit: " << s[s.size() - 1] << std::endl;
}
std::cin.sync(); std::cin.get();
return 0;
}
Avoid duplicates of the using keyword using.
Also consider switching from int to long or long long when your numbers get bigger. Since the fibonacci numbers are positive, also use unsigned.

Using char arrays to add together large numbers

I have an assignment in which I am supposed to
1.) Read in 2 char arrays of numbers
2.) add together the arrays, performing carry addition, carrying the tens place
3.) print out the newly added array.
I am also supposed to print an error if I need to carry on the last digit of the array (overflow)
so something like 99999999999999999999 +
1 =
________________________
ERROR
That's the part I'm having trouble with.
The above outputs something like "99999999999999999:0" so I have no idea what's going wrong.
I'll post my code, but please be nice :( I know it certainly isn't the most efficient, but I'm just trying to lay things out in a way that is easy for my brain to understand right now.
And yes, I HAVE to use char arrays. I guess it's to help us understand the ascii table.
#include <iostream>
using namespace std;
void InitNumber(char[]);
int AddArrays(char first[], char second[], char combined[]);
void OutputNumber (char[]);
const int LENGTH = 20; // global variable
int main()
{
char set1[LENGTH];
char set2[LENGTH];
char sum[LENGTH];
InitNumber (set1);
InitNumber (set2);
if(AddArrays (set1, set2, sum)) {
cout << "overflow!" << endl;
}
OutputNumber(sum);
}
void InitNumber (char list[])
{
int numberOfDigits;
cout << "Please enter the number of digits in the number: ";
cin >> numberOfDigits;
cout << "Please enter the digits in the number with the LEAST significant first: ";
for (int i = 0; i < numberOfDigits; i++) {
cin >> list [i];
}
for (int l=(numberOfDigits); l < LENGTH; l++) {
list [l] = '0';
}
}
int AddArrays(char first[], char second[], char combined[])
{
for (int h = 0; h < LENGTH; h++)
combined[h]= '0';
int overflow = 0;
for (int i = 0; i < LENGTH; i++) {
int currentSum = (first[i]-'0' + second[i]-'0');
cout << "currentSum = " << currentSum << endl;
if(currentSum / 10 == 0 )
combined[i] += currentSum;
else if (currentSum/10 !=0) {
if (i == LENGTH-1 && currentSum/10 !=0){
overflow = 1;
}
else{
combined [i] += currentSum%10;
cout << "current i: " << combined[i] << endl;
combined [i+1] += currentSum/10;
cout << "current i+1: " << combined[i+1] << endl;
}
}
}
return overflow;
}
void OutputNumber(char arrayOut[])
{
for (int l=LENGTH - 1; l >= 0; l--)
cout << arrayOut[l];
}
working input
input
6
1 2 3 4 5 6
7
1 2 3 4 5 6 7
output
00000000000008308642
Not-working output
input
20
9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
1
1
output
999999999999999999:0
I'm going to reproduce small parts of your inner loop where you are carrying out the addition, in order to explain why your overflow detection is broken.
for (int i = 0; i < LENGTH; i++) {
int currentSum = (first[i]-'0' + second[i]-'0');
if(currentSum / 10 == 0 )
combined[i] += currentSum;
Here you're adding the corresponding pair of digits from the two numbers you're adding, and checking (in your particular style) if they overflowed. Try to remember this part, it's important. In order to check for overflow, you're only checking the result of adding the pair of digits from the two large numbers you're adding.
else if (currentSum/10 !=0) {
This is a completely useless check. You can only get here if the division is known to produce a non-zero result. This if() can be removed completely. Now, the relevant part of your code is
combined [i] += currentSum%10;
combined [i+1] += currentSum/10;
Do you see the problem yet?
Your approach is, once overflow is detected, is to increment the next higher order digit in the result.
Unfortunately, on the next loop iteration, in order to check for carry over, you're just checking the sum of the next corresponding digit pair, from the two large numbers you're adding. The carry-over you're saving here is going to get completely ignored.
Say your numbers are two digits long max, rather than 20, and you entered the numbers 99 and 1.
On the first iteration, you'll add 9 and 1, save 0 as the first digit, and add 1 to the second digit in the sum.
On the second iteration, you'll add 9 and 0, and, given your logic above, conclude that nothing overflowed.