Ok so, I'm doing hackerrank's Fibonacci modified question. I am able to solve this question only when the iteration goes to 8 anything pass that and it starts returning a large negative number. I thought this was because of an integer overflow so I changed my types to unsigned long long yet the problems still persist. Any help is appreciated.
Link to original problem: https://www.hackerrank.com/challenges/fibonacci-modified/problem
#include <iostream>
#include <vector>
using namespace std;
int modFib(unsigned t1, unsigned t2, unsigned n) {
if (n == 1) {
return t1;
}
else if (n == 2) {
return t2;
} else {
return modFib(t1, t2, n-2) + (modFib(t1, t2, n-1) * modFib(t1, t2, n-1));
}
}
int main() {
cout << modFib(0, 1, 10) << endl;
return 0;
}
//Expected output is 84266613096281243382112
//I get -1022889632
In C++, the general range of an unsigned int is 0 to 4,294,967,295, so using an unsigned int will not be appropriate for this problem.
The expected output is actually larger than the maximum possible value of even an unsigned long long int, which goes from 0 to 18,446,744,073,709,551,615. This means that you cannot use either of these data types for this problem.
For such large values, you should look into the usage of BigNums.
Related
I am working on this LeetCode problem to take an integer and reverse it, given that the reversed in is within the signed 32-bit range, in which case we should return 0.
and this code is doing just that, even with numbers like 1534236469/-1534236469. Except when it comes to tricky numbers like -2147483648 where its not recognising it as out of range and instead returning 8 and not 0.
I know this is not the cleanest code, but can you help me recognise what I'm missing?
#include<iostream>
#include<limits>
using namespace std;
class Solution {
public:
int reverse(int x) {
int a, r, y;
string num, fnum;
a = abs(x);
try{
while(a != 0){
r = a % 10;
a = a / 10;
num = to_string(r);
fnum = fnum + num;
y = stoi(fnum);
}
} catch(out_of_range& oor){
return 0;
}
if(x==0){
return 0;
} else if (x<0){
return -y;
} else {
return y;
}
}
};
int main(){
Solution mine;
cout << mine.reverse(-2147483648);
}
[...] when it comes to tricky numbers like -2147483648 where its not recognising it as out of range and instead returning 8 and not 0.
That number is "tricky" because it's equal to std::numeric_limits<int>::min() in your environment and given a two's complement representation of type int, it happens that std::abs(-2147483648) == -2147483648.
Next in your (contrived, I must say, there's no need to use a string here) code, the line num = to_string(r); would result in num = "-8", so that the loop would compose a string like "-8-4-6-3-8-4-7-4-1-2".
When applyed to strings like that, stoi doesn't throw an exception, it just stops parsing (you would have noticed it by passing and inspecting its other parameters).
If you want to check if the result is outside the range of an int, you could use locally a wider type (e.g. long long) and check the boundaries after the calculations or keep using int, but compare all the intermediate values with the limits before any calculation.
I want to have it add every once a parameter it has not yet found to the map, but when I try numbers higher than 47 it gives me negative numbers, clearly impossible
#include <map>
using namespace std;
//memoization
map<unsigned int, unsigned int> memo;
map<unsigned int, unsigned int>::iterator it;
int fibonacci(int n)
{
it = memo.find(n);
if (it != memo.end())
{
cout << it->first<<endl;
return memo.at(n);
}
if (n <= 2)
{
return 1;
}
memo.insert({ n, fibonacci(n - 1) + fibonacci(n - 2) });
cout << "----"<<n<<endl;
return memo.at(n);
}
int main()
{
cout<<fibonacci(48);
}
First, let's take care of the negative numbers. Comments above explained that you have an overflow of the 32-bit int.
However, you could stretch your code a bit further would you not convert an unsigned int you calculate to a signed one you return from that function.
The solution is to use larger types, like unsigned long long int, AKA uint64_t
UPDATE
There are a few things sub-optimal in accepted answer.
As I noted in a comment there, the code is searching the map twice: it = memo.find(n); and memo[n];; should just return it->second;
There is no need for the key in that map to be 64-bit wide; 32 bit is enough to overflow 64-bit Fibonacci.
As the order of map keys is not important (you only do insert / lookup), the unordered_map will perform better (constant time instead of logarithmic).
You may notice that the memo is filled in order, and accessed by the index. Much better container here will be a vector with a "free" insert and lookup.
The calling function should NOT fill in memo, as it's not its business.
Here is my version:
#include <vector>
#include <iostream>
//memoization
static std::vector<uint64_t> memo = { 0, 0, 1 };
uint64_t fibonacci(unsigned int n) {
if (n < memo.size())
return memo[n];
memo.push_back(fibonacci(n - 1) + fibonacci(n - 2));
return memo[n];
}
int main() {
std::cout << fibonacci(32'000);
}
but when I try numbers higher than 47 it gives me negative numbers,
clearly impossible
unsigned int size is {0 to 4,294,967,295}, 48th Fibonacci is 4,807,526,976
Fixed code
#include <map>
#include <iostream>
#include <cstdint>
using namespace std;
//memoization
map<int64_t , int64_t> memo;
map<int64_t , int64_t>::iterator it;
int64_t fibonacci(int64_t n) {
it = memo.find(n);
if (it != memo.end()) {
return it->second;;
}
memo.insert({n, fibonacci(n - 1) + fibonacci(n - 2)});
return memo[n];
}
int main() {
memo.insert({0, 0});
memo.insert({1, 1});
memo.insert({2, 1});
cout << fibonacci(50);
}
I am getting negative output when adding large numbers in Fibonacci sequence despite using long int. How to fix that?
#include <iostream>
using namespace std;
void main() {
long int sum = 2;
long int f1 = 1, f2 = 2, f3;
for (unsigned int i = 2; i < 4000000; i++) {
f3 = f2 + f1;
if (!(f3 % 2)) {
sum += f3;
}
swap(f1, f2);
swap(f2, f3);
}
cout << sum << endl;
}
The output is -1833689714
As you can see here the 47th Fibonacci Number exceeds the range of a 32Bit/4Byte integer. Everything after that will become negative.
For your program you used a long int which may or may not be 32 or 64 bits wide, the C++ standard does not guarantee that (for good reasons). If I see your result it seems like 32 Bit for me.
First, to prevent negativeness, you could use unsigned long int which makes all your results positive and gives the ability to model "slightly" bigger numbers.
However you will still get the wrong results if you pass the 47th Fibonacci number since your data type is still too small. To fix this you could use unsigned long long or uint64_t.
Remember even for such big datatypes that can represent numbers up to approx. 18 trillion/quintillion (10^18) the Fibonacci numbers exceed this at the 89th iteration.
Try with this code:
#include<iostream>
using namespace std;
int main()
{
cout<<"Enter Number:";
unsigned long long int x;
cin>>x;
unsigned long long int a=0,b=1,c;
cout<<a<<"\t"<<b;
for(int i=0;i<x;i++)
{
c=a+b;
cout<<"\t"<<c;
a=b;
b=c;
return 0;
}
}
I compiled and run in my computer, and it executes correctly. I tried IDEONE, and I got a successful answer.
But when I submit it in SPOJ, I'm getting a wrong answer. Is something wrong in this implementation?
#include <iostream>
#include <cstdio>
using namespace std;
int factorial(int n) {
if (n <= 1)
return 1;
return n * factorial(n - 1);
}
int main() {
int t;
int n;
cout << "";
cin >> t;
for (int i = 0; i < t; i++) {
cout << "";
cin >> n;
printf("%d\n", factorial(n));
}
return 0;
}
The problem with the above code is due to the finite space we can use to store the value of an int. On a 32-bit machine, int's have 32 bits (value 0 or 1), which means that the maximum value an unsigned int can have is (2^31 - 1) and the maximum value an int can have is (2^30 - 1) (since it needs one bit to denote whether it is positive or negative, while the unsigned int is always positive and can devote that bit to just regular value).
Now, that aside, you should look into ways of storing the value of a very large number in a different data structure! Maybe an array would be a good choice...
Just to brainstorm, imagine creating an int bigInteger[100] (that should be large enough to hold 100!). To multiply two of your numbers, you could then implement a bitMultiplication(int bitNum[], int num) function that would take in your array by reference and perform bitwise multiplication (see the following post for details: Multiplying using Bitwise Operators).
Use that bitMulitiplication(int bitNum[], int num) instead of the regular multiplication in your recursive factorial function, and you should have a function that works on large n!
I just wrote this code :
#include <iostream>
using namespace std;
unsigned long long int choose(unsigned long long int k, unsigned long long int n)
{
if (k==n or k==0)
{
return 1;
}
else
{
return (choose(n-1,k-1)+choose(n-1,k));
}
}
int main(){
cout << choose(3, 6);
}
but I got Run-Time Error, I think my problem is in my variables, I did debugging but I couldn't find the answer, why I got run time error?
Since your variables are unsigned, substracting 1 from them when they're already 0 will make them roll over to the max value.
When n reaches 0 and you then call choose(n-1,k), this'll happen and that's the source of the issue (stackoverflow).