Computing fibonacci in c++ function and throwing compile-time error - c++

I need to write this function fibo.
If the number is too big it should be shown as compile error (the last line of main function)
The main function should stay like it is.
Any suggestions?
#include <iostream>
int fibo(int n)
{
if (n <= 1)
return n;
//if (n>=300) throws ... ?
return fibo(n - 1) + fibo(n - 2);
}
int main()
{
static_assert(fibo(7) == 34);
const int k = fibo(9);
std::cout << k << std::endl;
const int l = fibo(300); // 300th Fibonacci number is large for int
}

You can make fibo a constexpr function, and then throw if the argument is invalid. The throw in a constexpr function will lead to a compile time error if fibo is evaluated at compile time, and a run time error otherwise:
constexpr int fibo(int n)
{
if (n >= 300) throw;
if (n <= 1) return n;
return fibo(n-1) + fibo(n-2);
}
and you can use it like this:
int j = fibo(300); // run time error
constexpr int k = fibo(300); // compile time error
Here's a demo.
Note that you can't static_assert inside the definition of fibo since the condition depends on the function argument, which is not a constant expression.

Related

How to optimize Fibonacci using memoization in C++?

I'm struggling with getting the correct implementation of finding the nth number in the Fibonacci sequence. More accurately, how to optimize it with DP.
I was able to correctly write it in the bottom-up approach:
int fib(int n) {
int dp[n + 2];
dp[0] = 0;
dp[1] = 1;
for (int i = 2; i <= n; i++)
dp[i] = dp[i - 1] + dp[i - 2];
return dp[n];
}
But the top-down (memoized) approach is harder for me to grasp. This is what I put originally:
int fib(int n) {
std::vector<int> dp(n + 1, -1);
// Lambda Function
auto recurse = [&](int n) {
if (dp[n] != -1)
return dp[n];
if (n == 0) {
dp[n] = 0;
return 0;
}
if (n == 1){
dp[n] = 1;
return 1;
}
dp[n] = fib(n - 2) + fib(n - 1);
return dp[n];
};
recurse(n);
return dp.back();
}
...This was my first time using a C++ lambda function, though, so I also tried:
int recurse(int n, std::vector<int>& dp) {
if (dp[n] != -1)
return dp[n];
if (n == 0) {
dp[n] = 0;
return 0;
}
if (n == 1){
dp[n] = 1;
return 1;
}
dp[n] = fib(n - 2) + fib(n - 1);
return dp[n];
}
int fib(int n) {
std::vector<int> dp(n + 1, -1);
recurse(n, dp);
return dp.back();
}
...just to make sure. Both of these gave time limit exceeded errors on leetcode. This, obviously, seemed off, since DP/Memoization are optimization techniques. Is my top-down approach wrong? How do I fix it?
You set up the memoization storage in fib, and then create the recursive part of your solution in the lambda recurse. That means that here: dp[n] = fib(n - 2) + fib(n - 1); you really should call recurse not fib. But in order to do that with a lambda, you need to give the lambda to the lambda so to speak.
Example:
#include <iostream>
#include <vector>
int fib(int n)
{
std::vector<int> dp(n + 1, -1);
// Lambda Function
auto recurse = [&dp](int n, auto &rec)
{
if (dp[n] != -1)
return dp[n];
if (n == 0)
{
dp[n] = 0;
return 0;
}
if (n == 1)
{
dp[n] = 1;
return 1;
}
dp[n] = rec(n - 2, rec) + rec(n - 1, rec);
return dp[n];
};
recurse(n, recurse);
return dp.back();
}
int main()
{
std::cout << fib(12) << '\n';
}
Whenever you call fib(n), you create new vector dp with all element -1, then in fact, you don't memorize any previous result.
int fib(int n) {
std::vector<int> dp(n + 1, -1);
To solve this issue, you can declare dp vector outside the function as fib as shared data. Note that you said this is leetcode problem, then you can declare a vector with fixed size. For example,
std::vector<int> dp = std::vector<int>(31, -1);
You can test yourself. I just give the code which is runable in leetcode.
int fib(int n) {
// Lambda Function
auto recurse = [&](int n) {
if (n == 0) {
dp[n] = 0;
return 0;
}
if (n == 1){
dp[n] = 1;
return 1;
}
if (dp[n] != -1)
return dp[n];
dp[n] = fib(n - 2) + fib(n - 1);
return dp[n];
};
recurse(n);
return dp[n];
}
Very interesting. I will show you the fastest possible solution with an additional low memory footprint.
For this we will use compile time memoization.
One important property of the Fibonacci series is that the values grow strongly exponential. So, all existing build in integer data types will overflow rather quick.
With Binet's formula you can calculate that the 93rd Fibonacci number is the last that will fit in a 64bit unsigned value.
And calculating 93 values during compilation is a really simple and fast task.
So, how to do?
We will first define the default approach for calculation a Fibonacci number as a constexpr function. Iterative and non recursive.
// Constexpr function to calculate the nth Fibonacci number
constexpr unsigned long long getFibonacciNumber(size_t index) noexcept {
// Initialize first two even numbers
unsigned long long f1{ 0 }, f2{ 1 };
// calculating Fibonacci value
while (index--) {
// get next value of Fibonacci sequence
unsigned long long f3 = f2 + f1;
// Move to next number
f1 = f2;
f2 = f3;
}
return f2;
}
With that, Fibonacci numbers can easily be calculated at compile time. Then, we fill a std::array with all Fibonacci numbers. We use also a constexpr and make it a template with a variadic parameter pack.
We use std::integer_sequence to create a Fibonacci number for indices 0,1,2,3,4,5, ....
That is straigtforward and not complicated:
template <size_t... ManyIndices>
constexpr auto generateArrayHelper(std::integer_sequence<size_t, ManyIndices...>) noexcept {
return std::array<unsigned long long, sizeof...(ManyIndices)>{ { getFibonacciNumber(ManyIndices)... } };
};
This function will be fed with an integer sequence 0,1,2,3,4,... and return a std::array<unsigned long long, ...> with the corresponding Fibonacci numbers.
We know that we can store maximum 93 values. And therefore we make a next function, that will call the above with the integer sequence 1,2,3,4,...,92,93, like so:
constexpr auto generateArray() noexcept {
return generateArrayHelper(std::make_integer_sequence<size_t, MaxIndexFor64BitValue>());
}
And now, finally,
constexpr auto FIB = generateArray();
will give us a compile-time std::array<unsigned long long, 93> with the name FIB containing all Fibonacci numbers. And if we need the i'th Fibonacci number, then we can simply write FIB[i]. There will be no calculation at runtime.
I do not think that there is a faster or easier way to calculate the n'th Fibonacci number.
Please see the complete program below:
#include <iostream>
#include <array>
#include <utility>
// ----------------------------------------------------------------------
// All the following will be done during compile time
// Constexpr function to calculate the nth Fibonacci number
constexpr unsigned long long getFibonacciNumber(size_t index) {
// Initialize first two even numbers
unsigned long long f1{ 0 }, f2{ 1 };
// calculating Fibonacci value
while (index--) {
// get next value of Fibonacci sequence
unsigned long long f3 = f2 + f1;
// Move to next number
f1 = f2;
f2 = f3;
}
return f2;
}
// We will automatically build an array of Fibonacci numberscompile time
// Generate a std::array with n elements
template <size_t... ManyIndices>
constexpr auto generateArrayHelper(std::integer_sequence<size_t, ManyIndices...>) noexcept {
return std::array<unsigned long long, sizeof...(ManyIndices)>{ { getFibonacciNumber(ManyIndices)... } };
};
// Max index for Fibonaccis that for in an 64bit unsigned value (Binets formula)
constexpr size_t MaxIndexFor64BitValue = 93;
// Generate the required number of elements
constexpr auto generateArray()noexcept {
return generateArrayHelper(std::make_integer_sequence<size_t, MaxIndexFor64BitValue>());
}
// This is an constexpr array of all Fibonacci numbers
constexpr auto FIB = generateArray();
// ----------------------------------------------------------------------
// Test
int main() {
// Print all possible Fibonacci numbers
for (size_t i{}; i < MaxIndexFor64BitValue; ++i)
std::cout << i << "\t--> " << FIB[i] << '\n';
return 0;
}
Developed and tested with Microsoft Visual Studio Community 2019, Version 16.8.2.
Additionally compiled and tested with clang11.0 and gcc10.2
Language: C++17

Time limit exceeded issue in c++ UVa problem for university homework

I have a Time limit exceeded issue in problem 100 from UVa.
the question is here:
https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=24&page=show_problem&problem=36
Here is my code. Please help me find a solution. How can I avoid such problems?
I don't know if it is the problem with cin and cout or the while loops? this program works well in my terminal when I run it.
#include <iostream>
using namespace std;
int main()
{
int i , j, temp, n;
while (cin >> i >> j) //asking for user input
{
int x, y;
x = i;
y = j;
if (i > j) //sorting i and j to fix the order of numbers
{
temp = j;
j = i;
i = temp;
}
int answer = 0;
int counter;
while (i <= j)
{
n = i;
counter = 1; // make the value of counter to 1 because it increases if i is 1
while (1)
{
if(n == 1) { //if n = 1 then stop
break;
} else if (n % 2 == 0) //cheak if i is odd
{
n = (3 % n) + 1;
} else {
n = n / 2; //cheak if i is even
}
counter++; //increase by one for every number that is not 1
}
if (counter > answer)
{
answer = counter;
}
i++;
}
cout << x << " " << y << " " << answer << "\n";
}
return 0;
}
Thanks in advance
In my humble opinion this problem is not about calculating the resulting values using the given algorithm. Because of the simplicity this is just some noise. So,maybe we are talking about a XY Problem here.
Maybe I am wrong, but the main problem here seems to be memoization.
It maybe that values need to be calculated over and over again, because they are in some overlapped range. And this is not necessary.
So, we could memorize already calculated values, for example in a std::unordered_map (or std::map). So, something like in the below:
unsigned int getSteps(size_t index) noexcept {
unsigned counter{};
while (index != 1) {
if (index % 2) index = index * 3 + 1;
else index /= 2;
++counter;
}
return counter+1;
}
unsigned int getStepsMemo(size_t index) {
// Here we will memorize whatever we calculated before
static std::unordered_map<unsigned int, unsigned int> memo{};
// Resulting value
unsigned int result{};
// Look, if we did calculate the value in the past
auto iter = memo.find(index);
if (iter != memo.end())
// If yes, then reuse old value
result = iter->second;
else {
// If no, then calculate new and memorize it
result = getSteps(index);
memo[index] = result;
}
return result;
}
This will help with many given input pairs. It will avoid recalculating steps for already calculated values.
But having thought in this direction, we can also calculate all values at compile time and store them in a constexpr std::array. Then no calculation will be done during runtime. All steps for any number up to 10000 will be precalculated. So, the algorithm will never be called during runtime.
It should be clear that this is the fastest possible algorithm, because we do nothing. Just get the value from a lookup table.
And if we want to make things nice, then we pack everything in a class and let the class encapsulate the problem. Even input and output operatores will be overwritten and used for our own purposes.
And in the end, we will have an ultra fast one liner in our function main. Please see:
#include <iostream>
#include <utility>
#include <sstream>
#include <array>
#include <algorithm>
#include <iterator>
#include <unordered_map>
// All done during compile time -------------------------------------------------------------------
constexpr unsigned int getSteps(size_t index) noexcept {
unsigned counter{};
while (index != 1) {
if (index % 2) index = index * 3 + 1;
else index /= 2;
++counter;
}
return counter+1;
}
// Some helper to create a constexpr std::array initilized by a generator function
template <typename Generator, size_t ... Indices>
constexpr auto generateArrayHelper(Generator generator, std::index_sequence<Indices...>) {
return std::array<decltype(std::declval<Generator>()(size_t{})), sizeof...(Indices) > { generator(Indices+1)... };
}
template <size_t Size, typename Generator>
constexpr auto generateArray(Generator generator) {
return generateArrayHelper(generator, std::make_index_sequence<Size>());
}
constexpr size_t MaxIndex = 10000;
// This is the definition of a std::array<unsigned long long, 10000> with all step counts
constexpr auto steps = generateArray<MaxIndex>(getSteps);
// End of: All done during compile time -----------------------------------------------------------
// Some very simple helper class for easier handling of the functionality
struct StepsForPair {
// A pair with special functionality
unsigned int first{};
unsigned int second{};
// Simple extraction operator. Read 2 values
friend std::istream& operator >> (std::istream& is, StepsForPair& sfp) {
return is >> sfp.first >> sfp.second;
}
// Simple inserter. Sort first and second value and show result
friend std::ostream& operator << (std::ostream& os, const StepsForPair& sfp) {
unsigned int f{ sfp.first }, s{ sfp.second };
if (f > s) std::swap(f, s);
return os << sfp.first << ' ' << sfp.second << ' ' << *std::max_element(&steps[f], &steps[s]);
}
};
// Some test data. I will not use std::cin, but read from this std::istringstream here
std::istringstream testData{ R"(1 10
100 200
201 210
900 1000
22 22)" };
int main() {
// Read all input data and generate output
std::copy(std::istream_iterator<StepsForPair>(testData), {}, std::ostream_iterator<StepsForPair>(std::cout,"\n"));
}
Please note, since I do not have std::cin here on SO, I read the test values from a std::istringstream. Because of the overwritten extractor operator, this is easily possible.
If you want to read from std::cin then please replace in the std::copy statement in main "testData" eith "std::cin".
If you want to read from a file, then put a fileStream variable in there.
In this line n = (3 % n) + 1;, (3 % n) means that you take the remainder of 3 divided by n, which is probably not what you want. Change that to 3 * n

Fibonacci memoization algorithm in C++

I'm struggling a bit with dynamic programming. To be more specific, implementing an algorithm for finding Fibonacci numbers of n.
I have a naive algorithm that works:
int fib(int n) {
if(n <= 1)
return n;
return fib(n-1) + fib(n-2);
}
But when i try to do it with memoization the function always returns 0:
int fib_mem(int n) {
if(lookup_table[n] == NIL) {
if(n <= 1)
lookup_table[n] = n;
else
lookup_table[n] = fib_mem(n-1) + fib_mem(n-2);
}
return lookup_table[n];
}
I've defined the lookup_table and initially stored NIL in all elements.
Any ideas what could be wrong?
Here's the whole program as requested:
#include <iostream>
#define NIL -1
#define MAX 100
long int lookup_table[MAX];
using namespace std;
int fib(int n);
int fib_mem(int n);
void initialize() {
for(int i = 0; i < MAX; i++) {
lookup_table[i] == NIL;
}
}
int main() {
int n;
long int fibonnaci, fibonacci_mem;
cin >> n;
// naive solution
fibonnaci = fib(n);
// memoized solution
initialize();
fibonacci_mem = fib_mem(n);
cout << fibonnaci << endl << fibonacci_mem << endl;
return 0;
}
int fib(int n) {
if(n <= 1)
return n;
return fib(n-1) + fib(n-2);
}
int fib_mem(int n) {
if(lookup_table[n] == NIL) {
if(n <= 1)
lookup_table[n] = n;
else
lookup_table[n] = fib_mem(n-1) + fib_mem(n-2);
}
return lookup_table[n];
}
I tend to find the easiest way to write memoization by mixing the naive implementation with the memoization:
int fib_mem(int n);
int fib(int n) { return n <= 1 ? n : fib_mem(n-1) + fib_mem(n-2); }
int fib_mem(int n)
{
if (lookup_table[n] == NIL) {
lookup_table[n] = fib(n);
}
return lookup_table[n];
}
#include <iostream>
#define N 100
using namespace std;
const int NIL = -1;
int lookup_table[N];
void init()
{
for(int i=0; i<N; i++)
lookup_table[i] = NIL;
}
int fib_mem(int n) {
if(lookup_table[n] == NIL) {
if(n <= 1)
lookup_table[n] = n;
else
lookup_table[n] = fib_mem(n-1) + fib_mem(n-2);
}
return lookup_table[n];
}
int main()
{
init();
cout<<fib_mem(5);
cout<<fib_mem(7);
}
Using the exactly same function, and this is working fine.
You have done something wrong in initialisation of lookup_table.
Since the issue is initialization, the C++ standard library allows you to initialize sequences without having to write for loops and thus will prevent you from making mistakes such as using == instead of =.
The std::fill_n function does this:
#include <algorithm>
//...
void initialize()
{
std::fill_n(lookup_table, MAX, NIL);
}
Interesting concept. Speeding up by memoization.
There is a different concept. You could call it compile time memoization. But in reality it is a compile time pre calculation of all Fibonacci numbers that fit into a 64 bit value.
One important property of the Fibonacci series is that the values grow strongly exponential. So, all existing build in integer data types will overflow rather quick.
With Binet's formula you can calculate that the 93rd Fibonacci number is the last that will fit in a 64bit unsigned value.
And calculating 93 values during compilation is a really simple task.
We will first define the default approach for calculation a Fibonacci number as a constexpr function:
// Constexpr function to calculate the nth Fibonacci number
constexpr unsigned long long getFibonacciNumber(size_t index) noexcept {
// Initialize first two even numbers
unsigned long long f1{ 0 }, f2{ 1 };
// calculating Fibonacci value
while (index--) {
// get next value of Fibonacci sequence
unsigned long long f3 = f2 + f1;
// Move to next number
f1 = f2;
f2 = f3;
}
return f2;
}
With that, Fibonacci numbers can easily be calculated at runtime. Then, we fill a std::array with all Fibonacci numbers. We use also a constexpr and make it a template with a variadic parameter pack.
We use std::integer_sequence to create a Fibonacci number for indices 0,1,2,3,4,5, ....
That is straigtforward and not complicated:
template <size_t... ManyIndices>
constexpr auto generateArrayHelper(std::integer_sequence<size_t, ManyIndices...>) noexcept {
return std::array<unsigned long long, sizeof...(ManyIndices)>{ { getFibonacciNumber(ManyIndices)... } };
};
This function will be fed with an integer sequence 0,1,2,3,4,... and return a std::array<unsigned long long, ...> with the corresponding Fibonacci numbers.
We know that we can store maximum 93 values. And therefore we make a next function, that will call the above with the integer sequence 1,2,3,4,...,92,93, like so:
constexpr auto generateArray() noexcept {
return generateArrayHelper(std::make_integer_sequence<size_t, MaxIndexFor64BitValue>());
}
And now, finally,
constexpr auto FIB = generateArray();
will give us a compile-time std::array<unsigned long long, 93> with the name FIB containing all Fibonacci numbers. And if we need the i'th Fibonacci number, then we can simply write FIB[i]. There will be no calculation at runtime.
I do not think that there is a faster way to calculate the n'th Fibonacci number.
Please see the complete program below:
#include <iostream>
#include <array>
#include <utility>
// ----------------------------------------------------------------------
// All the following will be done during compile time
// Constexpr function to calculate the nth Fibonacci number
constexpr unsigned long long getFibonacciNumber(size_t index) {
// Initialize first two even numbers
unsigned long long f1{ 0 }, f2{ 1 };
// calculating Fibonacci value
while (index--) {
// get next value of Fibonacci sequence
unsigned long long f3 = f2 + f1;
// Move to next number
f1 = f2;
f2 = f3;
}
return f2;
}
// We will automatically build an array of Fibonacci numberscompile time
// Generate a std::array with n elements
template <size_t... ManyIndices>
constexpr auto generateArrayHelper(std::integer_sequence<size_t, ManyIndices...>) noexcept {
return std::array<unsigned long long, sizeof...(ManyIndices)>{ { getFibonacciNumber(ManyIndices)... } };
};
// Max index for Fibonaccis that for in an 64bit unsigned value (Binets formula)
constexpr size_t MaxIndexFor64BitValue = 93;
// Generate the required number of elements
constexpr auto generateArray()noexcept {
return generateArrayHelper(std::make_integer_sequence<size_t, MaxIndexFor64BitValue>());
}
// This is an constexpr array of all Fibonacci numbers
constexpr auto FIB = generateArray();
// ----------------------------------------------------------------------
// Test
int main() {
// Print all possible Fibonacci numbers
for (size_t i{}; i < MaxIndexFor64BitValue; ++i)
std::cout << i << "\t--> " << FIB[i] << '\n';
return 0;
}
Developed and tested with Microsoft Visual Studio Community 2019, Version 16.8.2.
Additionally compiled and tested with clang11.0 and gcc10.2
Language: C++17
There's a mistake in your initialize() function:
void initialize() {
for(int i = 0; i < MAX; i++) {
lookup_table[i] == NIL; // <- mistake
}
}
In the line pointed you compare lookup_table[i] and NIL (and don't use the result) instead of assigning NIL to lookup_table[i].
For assignment, you should use = instead of ==.
Also, in such situations the most right thing to do is compilation of your program with all warnings enabled. For example, MS VC++ shows the following warning:
warning C4553: '==': operator has no effect; did you intend '='?
The error is on initialize function (you've used comparison operator '==' where you want a attribution operator '='). But, on semantics, you don't need initialize look_table with -1 (NIL) because Fibonacci results never will be 0 (zero); so, you can initialize it all with zero.
Look below the final solution:
#include <iostream>
#define NIL 0
#define MAX 1000
long int lookup_table[MAX] = {};
using namespace std;
long int fib(int n) {
if(n <= 1)
return n;
return fib(n-1) + fib(n-2);
}
long int fib_mem(int n) {
assert(n < MAX);
if(lookup_table[n] == NIL) {
if(n <= 1)
lookup_table[n] = n;
else
lookup_table[n] = fib_mem(n-1) + fib_mem(n-2);
}
return lookup_table[n];
}
int main() {
int n;
long int fibonnaci, fibonacci_mem;
cout << " n = "; cin >> n;
// naive solution
fibonnaci = fib(n);
// memoized solution
// initialize();
fibonacci_mem = fib_mem(n);
cout << fibonnaci << endl << fibonacci_mem << endl;
return 0;
}

Implements neper number (e) with a recursion function

I want to calculate Neper number(e) with a recursion function. I have the formula to calculate it:
e = (1/0!) + (1/1!) + (1/2!) + (1/3!) +. . .
I have the code but it won't work properly:
#include <iostream>
using namespace std;
double f(double res,int i, int n){
return (i == n) ? res: res = res + (1 /f(res,i+1,n)*i);
}
int main(){
cout << f(1,1,2) << endl;
}
The result of this code is 2.5 but it should be 2. Where is the problem?
Still not sure what you want res for. In fact, if I got creative with the sign of n this doesn't need i either.
double f(int i, int n)
{
return (i == 0) ? ((n <= 1) ? 1 : n * f(0,n-1))
: ((n < 1) ? 1 : 1/f(0, n) + f(i,n-1));
}
int main()
{
for (int n=1; n<16; ++n)
std::cout << std::setprecision(16) << f(1,n) << std::endl;
return 0;
}
Output
2
2.5
2.666666666666667
2.708333333333333
2.716666666666666
2.718055555555555
2.718253968253968
2.71827876984127
2.718281525573192
2.718281801146385
2.718281826198493
2.718281828286169
2.718281828446759
2.71828182845823
2.718281828458995
This was what I meant about toying with the sign for n to eliminate i as well:
double f(int n)
{
return (n < 0) ? ((n == -1) ? 1 : -n * f(n+1))
: ((n < 1) ? 1 : 1/f(-n) + f(n-1));
}
The results are the same. In both cases the function is defined to dual-purpose it recursive algorithm. When asked to, it computes 1/n!, otherwise it computes the running sum + the next number down (which is 1/(n-1)!, etc...)
I think you are referring to Napier, the inventor of the logarithm.
To compute 1/0!+1/1!+1/2!+...+1/n! recursively and efficiently, you can refactor it as 2+1/2*(1+1/3*(1+...1/n))) to obtain the recursive definition
h(k,n)=(k==n)?1.0/n:(1.0+h(k+1,n)/k)
f(n)=1+h(2,n)
You will get faster convergence by using the properties of the exponential function, for instance that e=exp(1/8)^8, also known as the strategy of halving-and-squaring.

Recursion function to find power of number

I'm writing a recursion function to find the power of a number and it seems to be compiling but doesn't output anything.
#include <iostream>
using namespace std;
int stepem(int n, int k);
int main()
{
int x, y;
cin >> x >> y;
cout << stepem(x, y) << endl;
return 0;
}
int stepem(int n, int k)
{
if (n == 0)
return 1;
else if (n == 1)
return 1;
else
return n * stepem(n, k-1);
}
I tried debugging it, and it says the problem is on this line :
return n * stepem(n, k-1);
k seems to be getting some weird values, but I can't figure out why?
You should be checking the exponent k, not the number itself which never changes.
int rPow(int n, int k) {
if (k <= 0) return 1;
return n * rPow(n, --k);
}
Your k is getting weird values because you will keep computing until you run out of memory basically, you will create many stack frames with k going to "-infinity" (hypothetically).
That said, it is theoretically possible for the compiler to give you a warning that it will never terminate - in this particular scenario. However, it is naturally impossible to solve this in general (look up the Halting problem).
Your algorithm is wrong:
int stepem(int n, int k)
{
if (k == 0) // should be k, not n!
return 1;
else if (k == 1) // this condition is wrong
return 1;
else
return n * stepem(n, k-1);
}
If you call it with stepem(2, 3) (for example), you'll get 2 * 2 * 1 instead of 2 * 2 * 2 * 1. You don't need the else-if condition:
int stepem(int n, unsigned int k) // unless you want to deal with floating point numbers, make your power unsigned
{
if (k == 0)
return 1;
return n * stepem(n, k-1);
}
Didn't test it but I guess it should give you what you want and it is tail recursive.
int stepemi(int result, int i int k) {
if (k == 0 && result == i)
return 1;
else if (k == 0)
return result;
else
return stepem(result * i, i, k-1);
}
int stepem(int n, int k) {
return stepemi(n, n, k);
}
The big difference between this piece of code and the other example is that my version could get optimized for tail recursive calls. It means that when you call stepemi recursively, it doesn't have to keep anything in memory. As you can see, it could replace the variable in the current stack frame without having to create a new one. No variable as to remain in memory to compute the next recursion.
If you can have optimized tail recursive calls, it also means that the function will used a fixed amount of memory. It will never need more than 3 ints.
On the other hand, the code you wrote at first creates a tree of stackframe waiting to return. Each recursion will add up to the next one.
Well, just to post an answer according to my comment (seems I missed adding a comment and not a response :-D). I think, mainly, you have two errors: you're checking n instead of k and you're returning 1 when power is 1, instead of returning n. I think that stepem function should look like:
Edit: Updated to support negative exponents by #ZacHowland suggestion
float stepem(int n, int k)
{
if (k == 0)
return 1;
else
return (k<0) ?((float) 1/n) * stepem(n, k+1) :n * stepem(n, k-1);
}
// Power.cpp : Defines the entry point for the console application.
//
#include <stream>
using namespace std;
int power(int n, int k);
void main()
{
int x,y;
cin >>x>>y;
cout<<power(x,y)<<endl;
}
int power(int n, int k)
{
if (k==0)
return 1;
else if(k==1) // This condition is working :) //
return n;
else
return n*power(n,k-1);
}
your Program is wrong and it Does not support negative value given by user,
check this one
int power(int n, int k){
'if(k==0)
return 1;
else if(k<0)
return ((x*power(x,y+1))*(-1));
else
return n*power(n,k-1);
}
sorry i changed your variable names
but i hope you will understand;
#include <iostream>
using namespace std;
double power(double , int);// it should be double because you also need to handle negative powers which may cause fractions
int main()
{
cout<<"please enter the number to be powered up\n";
double number;
cin>>number;
cout<<"please enter the number to be powered up\n";
int pow;
cin>>pow;
double result = power(number, pow);
cout<<"answer is "<<result <<endl;
}
double power( double x, int n)
{
if (n==0)
return 1;
if (n>=1)
/*this will work OK even when n==1 no need to put additional condition as n==1
according to calculation it will show x as previous condition will force it to be x;
try to make pseudo code on your note book you will understand what i really mean*/
if (n<0)
return x*power(x, n-1);
return 1/x*power(x, n+1);// this will handle negative power as you should know how negative powers are handled in maths
}
int stepem(int n, int k)
{
if (k == 0) //not n cause you have to vary y i.e k if you want to find x^y
return 1;
else if (k == 1)
return n; //x^1=x,so when k=1 it should be x i.e n
else
return n * stepem(n, k-1);
}