There is the recursive function in my program for finding the factorial of the number. In this program i want to find the factorial of 4. I stored the value 4 in to the variable n through cin. While writing a factorial function, we can stop recursive calling when n is 2 or 1. Below is the code of my program for finding the factorial of the number.
#include <iostream>
using namespace std;
long factorial(long );
int main()
{
long n;
cin>>n;
cout<< "factorial= "<<factorial(n);
}
long factorial(long n)
{
if(n<=2)
return 2;
else
return n*factorial(n-1);
}
The output of this program in console window is factorial= 24 which is the correct output. The return statement causes a function to end immediately and a function may send a value back to the part of the program that called the function. There are two return statements in the called function of the above program. The called function is returning the value 24 to the calling program which is the factorial of 4. The called function is not returning any value of the first return statement to the calling program. I modified the above program. Below is the code of the program in which i changed the first return statement of the called program.
#include <iostream>
using namespace std;
long factorial(long );
int main()
{
long n;
cin>>n;
cout<< "factorial= "<<factorial(n);
}
long factorial(long n)
{
if(n<=2)
return 1;
else
return n*factorial(n-1);
}
The output of this program in console window is factorial= 12 which is not the correct output. Why the called function is returning the value 12 to the calling program instead of 24 after changing the return statement after conditional statement which is if(n<=2)?
you get 12 because you do not multiply by 2 anymore for 2.
so you call it with 4.. which calls it with 3, 2, and 1 ...
in the top one, if its 2, you return 2, so you get 2*3*4 = 24.
in the bottom one, if its 2, you return 1, so you get 1* 3*4
the top one is correct unless you call it with factorial 0 or 1. Those are special cases you need to handle. 0 -> 1, 1 ->1 , 2->2, 3->6, 4 -> 24 ... and so on.
When posting code, it's helpful for those trying to read it if code tags are used:
[code]
//formatted code goes here
[/code]
Also, when asking for input from the console, it's usual for a prompt to be provided sttaing what input is expected.
Consider:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
#include <iostream>
using Num = unsignedlonglong;
[[nodiscard]]
inline Num factorial(Num n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
int main() {
Num n {};
std::cout << "Enter number for factorial: ";
std::cin >> n;
std::cout << "factorial= " << factorial(n) << '\n';
}
Hello. Respectfully you have to format your code in order to get some readability. It's good for you - it's good for us. Unsigned long long integer is the largest (64 bits) integer data type in C++. The maximum you can get is 18446744073709551615. Out of this integer your value is truncated. So you should check your entry.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// https://en.wikipedia.org/wiki/Factorial
#include <iostream>
unsignedlonglong factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
int main()
{
int n;
std::cout << "Enter number for factorial (max 20) : ";
std::cin >> n;
n > 20 ? std::cout << "no more 20 I said!" << std::endl
: std::cout << "factorial = " << factorial(n) << std::endl;
return 0;
}
Out of context, when I write a large code, I like to put useful functions inside a structure or a class as static members. This way I can easily reuse them. Just a little tip for friends :)
@seeplus you used an inline function - and I guess that we should. Without it, do you think that there is a waste of memory - even using a recursive function? I have a doubt. Thanks ++
I too am curious about the inline, but..
the zero propagation makes this interesting for use with floating point values, or pseudo-floating point values where you keep the power of 10 aside from the other digits. At 'only' 20 you already use 4 of your digits as zeros. I don't know what it looks like in binary, but there is probably a similar redundancy if you spent some time looking at it... after all, every value after the first few are shifted from a 2, 4, 8 value..
anyway, for whatever nutty reason, you can squeeze a few more out of it by some sort of zero reduction, in whatever base.
unfortunately, I don't know that double gains much, even though it 'drops' the zeros it doesn't have the sig figs to keep up so you approximate pretty soon.
> you used an inline function - and I guess that we should. Without it, do you think that there is a waste of memory ...
In pre-historic days, the primary intent of the inline specifier for a function was to provide a strong hint to the optimiser - 'inline substitution of this function is preferred'. Over a period of time, as optimisers became more intelligent, this usage of inline has become an obsolete relic.
cppreference:
... compilers are free to use inline substitution for any function that's not marked inline, and are free to generate function calls to any function marked inline. Those optimization choices do not change the rules regarding multiple definitions and shared statics listed above.
(since C++17)
Because the meaning of the keyword inline for functions came to mean "multiple definitions are permitted" rather than "inlining is preferred", that meaning was extended to variables. https://en.cppreference.com/w/cpp/language/inline#Explanation
Thank you @JLBorges for the clever answer.
There are many other ways to do factorial computations. Some of them are very interesting using vector and multiplication ++
That's not yet C++ standard and isn't supported by all compilers (eg not by VS).
If a integral number larger than allowed for with unsigned long long (usually uint64) then there are various large integer libraries available.
@seeplus you used an inline function
As per JLBorges answer for C++17 re permitted multiple definitions, we mark all of our 'utility' functions inline for this reason. As factorial is recursive, the compiler would ignore the 'original' meaning of inline anyhow as you can't 'inline' code for a run-time recursive function.
Note lastchance's usage of tgamma() to obtain the factorial. It uses an argument of N + 1 as tgamma() calculates (N - 1)! for natural numbers.
> you can't 'inline' code for a recursive function.
Inline substitution may be performed for any function, including recursive functions.
The only requirement is that the observable behaviour of the program is not changed.
1 2 3 4 5 6 7 8 9 10 11
staticunsignedlonglong fact( unsignedint n ) noexcept
{ return n < 2 ? 1 : n * fact(n-1) ; } // recursive
unsignedlonglong foo() noexcept // evaluated at compile time
{ return fact(10) ; } // return 3628800
unsignedlonglong bar() noexcept // evaluated at compile time
{ return fact(12) / fact(10) ; } // return 132
unsignedlonglong baz( unsignedint n ) noexcept
{ return fact(n) ; } // loop (inline substitution of the recursive function fact)
> OK - for a function that can be evaluated at compile time.
Inline substitution may be performed for any function, as long as the observable behaviour of the program is not changed.
1 2 3 4 5
staticunsignedlonglong fact( volatileunsignedint n ) noexcept
{ return n < 2 ? 1 : n * fact(n-1) ; } // can't be evaluated at compile-time
unsignedlonglong baz( unsignedint n ) noexcept
{ return fact(n) ; } // loop (inline substitution of the recursive function fact)
Yes - any modern optimising compiler (if instructed) is free to optimise the generated code anyhow it thinks appropriate whilst maintaining the original program behaviour. As JLBorges mentioned above, the original purpose of inline as an optimisation hint to the compiler is now largely redundant as modern C++ compilers are so much better at optimisation than their historical versions - with the C++17 meaning prevalent.
Also worth noting that sometimes inline (referring to "forcing" inline via the compiler) can make things faster, but other times it can make things slower (due to instruction cache size limits, I think). It can sometimes be a delicate balance.
inline doesn't and never has forced inlining for the compiler. It was only a guide to the compiler to consider inlining that function. The compiler was/is quite at liberty to ignore it. Also if the code is inlined by the compiler this can make the size of the generated code larger. If the size of the generated code file is important then you may not want functions inlined. With VS you can instruct the compiler to optimize/favour either speed or size.
visual has the nonstandard force inline which supposedly does inline regardless -- unless its not possible. Its not generally possible to inline recursion if the recursive calls are actually made, and there are similar circumstances where it can't do it.
you can also skip all this and exploit #include or other macros to force inline a bit of code in extreme circumstances.