I wrote a simple C++ program that computes permutations/factorials in 2 different methods. The problem arises when I try to use the longer method (p1) with 20 and 2. Granted, "20!" is a HUGE number. Is there a limit with integers when calculating the factorial using the recursion method?
#include <iostream>
using namespace std;
int p1(int n, int r);
int p2(int n, int r);
int factorial(int x);
int main()
{
cout << p1(10, 8) << endl;
cout << p2(10, 8) << endl;
cout << p1(4, 3) << endl;
cout << p2(4, 3) << endl;
cout << p1(20, 2) << endl; // THE NUMBER PRINTS INCORRECTLY HERE
cout << p2(20, 2) << endl;
system("PAUSE");
return EXIT_SUCCESS;
}
int p1(int n, int r) // long version, recursively calls factorial
{
return (factorial(n) / factorial(n - r));
}
int factorial(int x)
{
if (x == 0)
return 1;
else if (x > 0)
return (x * factorial(x - 1));
}
int p2(int n, int r) // shortcut, does arithmetic in for loop
{
int answer = n;
for (int i = 1; i < r; i++)
{
answer *= n - 1;
n--;
}
return answer;
}
20! is 2.4*10^18
You can check out a reference of limits.h to see what the limits are.
consider that 2^32 is 4.2*10^9. long int is usually a 32-bit value.
consider that 2^64 is 1.8*10^19, so a 64-bit integer will get you through 20! but no more. unsigned long long int should do it for you then.
unsigned long long int p1(int n, int r)
{
return (factorial(n) / factorial(n - r));
}
unsigned long long int factorial(unsigned long long int x)
{
if (x == 0)
return 1;
else if (x > 0)
return (x * factorial(x - 1));
}
unsigned long long int p2(int n, int r)
{
unsigned long long int answer = n;
for (int i = 1; i < r; i++)
{
answer *= n - 1;
n--;
}
return answer;
}
If you are allowed in this assignment, consider using float or double, unless you need absolute precision, or just need to get to 20 and be done. If you do need absolute precision and to perform a factorial above 20, you will have to devise a way to store a larger integer in a byte array like #z32a7ul states.
Also you can save an operation by doing answer *= --n; to pre-decrement n before you use it.
20! exceeds the integer range. Your shortcut function doesn't exceed simply because you don't calculate the whole faculty, but 20*19
If you really need it, you may create a class that holds a variable-length array of bytes, and define operators on it. In that case, only the available memory and your patiance will limit the size of numbers. I think Scheme (a LISP dialect) does something like that.
Related
The following is the code:
#include
using namespace std;
int factorial(int num){
unsigned long long int fact=1;
for (int i = num; i >=1; i--)
{
fact=fact*i;
}
return fact;
}
int main()
{
unsigned long long int n,r,value;
cout<<"Enter a number whose nCr value is to be calculated (n and r respectively): ";
cin>>n>>r;
unsigned long long int a=factorial(n);
unsigned long long int b=factorial(r);
unsigned long long int c=factorial(n-r);
value=a/(b*c);
cout<<"The value of nCr is : "<<value;
return 0;
}
Why do I get the answer to some of the inputs like (30 15),(30 12), etc as 0.
30! is a very large 33-digit number, so that's overflowing the int variable your program is trying to store it in. If you print it out, you'll see the actual value that gets stored in a is smaller than the value of b*c in the denominator of the final computation, so value=a/(b*c); gets truncated to 0 by integer division.
Even if you return the result of factorial as an unsigned long long int the result of 30! will overflow, since it can only store 64 bits (and that's compiler dependent).
#include "stdafx.h"
#include <iostream>
unsigned long long int factorial(int num) {
unsigned long long int fact = 1;
for (int i = num; i >= 1; i--)
{
fact = fact * i;
}
return fact;
}
int main()
{
unsigned long long int n, r, value;
std::cout << "Enter a number whose nCr value is to be calculated (n and r respectively): ";
std::cin >> n >> r;
unsigned long long int a = factorial(n);
std::cout << "n! = " << a << std::endl;
unsigned long long int b = factorial(r);
std::cout << "r! = " << b << std::endl;
unsigned long long int c = factorial(n - r);
std::cout << "(n-r)! = " << c << std::endl;
std::cout << "r!(n-r)! = " << b*c << std::endl;
value = a / (b*c);
std::cout << "The value of nCr is : " << value << std::endl;
system("pause");
return 0;
}
Output:
Enter a number whose nCr value is to be calculated (n and r respectively): 30 12
n! = 9682165104862298112
r! = 479001600
(n-r)! = 6402373705728000
r!(n-r)! = 12940075575627743232
The value of nCr is : 0
Press any key to continue . . .
The main issue with your code is return type of factorial Method it should be same as the return type of "fact".
Second issue with code is that it cannot handle huge number above i.e, max value of unsigned long long int "18,446,744,073,709,551,615"(https://www.tutorialspoint.com/cplusplus/cpp_data_types.htm).
So just change the data types of variables fact,a,b,c and factorial method to "long double" which can accomodate 12 bytes of data.
Code below is just modified for tracing purpose... you can skip the line which you don't need. Be careful with data types. Code is modified as per your requirement for huge calculations.
Please reply if you have any confusion. And up-vote my answer if it looks right to you.
You can remove std:: from the code if not need by your compiler.
#include <iostream>
long double factorial(int num){
long double fact=1;
for (int i = num; i >=1; i--)
{
fact=fact*i;
}
return fact;
}
int main()
{
unsigned long long int n=0,r=0;
long double value=0;
std::cout<<"Enter a number whose nCr value is to be calculated (n and r respectively): ";
std::cin>>n>>r;
std::cout<<n;
std::cout<<r;
long double a=factorial(n);
long double b=factorial(r);
long double c=factorial(n-r);
std::cout<<"\na="<<a;
std::cout<<"\nb="<<b;
std::cout<<"\nc="<<c;
long double d = b*c;
std::cout<<"\nd="<<d;
value=(unsigned long long int)(a/d);
std::cout<<"\nThe value of nCr is : "<<value;
return 0;
`enter code here`}
The question I am trying to solve is:
Implement pow(x, n), which calculates x raised to the power n (Leetcode problem 50)
I have the following code:
class Solution {
public:
double myPow(double x, int n) {
if (n == 0) {
cout << "in last";
return 1;
} else if (n < 0) {
x = 1 / x;
return myPow(x, -n);
} else if (n % 2 == 0) {
double y;
cout << "in even";
y = myPow(x, n / 2);
cout << "y is ";
cout << y;
return (y * y);
}
else {
cout << "in odd";
double j = myPow(x, n - 1);
cout << "j is ";
cout << x * j;
return (x * j);
}
}
};
When ran for the test case x=1.00000 and n = -2147483648. I am getting the error:
runtime error: negation of -2147483648 cannot be represented in type 'int'; cast to an unsigned type to negate this value to itself (solution.cpp)
Why do I get this and how shall I solve it? TIA
If you want to support -2147483648 then you need to use a long long type, not an int.
If int is a 32 bit 2's complement type then 2147483648 is actually a long or a long long type.
There are no such things as negative literals in C++ (-2147483648 is a compile time evaluable constant expression consisting of the negation of the literal 2147483648), so -2147483648 is either a long or a long long type too. This is why you'll often see INT_MIN defined as -2147483647 - 1.
If the above is the case on your platform then the behaviour of your code is undefined for that input, as you are overflowing an int type.
A 4 bytes (or 32 bits) int has a range of -2,147,483,648 to 2,147,483,647, thus if you negate -2,147,483,648 you can't represent it as int.
You could try using unsigned int (which has a range of
0 to 4,294,967,295) or long long int (which a range of -(2^63) to (2^63)-1) make this negation and fit the positive value there.
I opted for a different approach and handled this case separately since it is the only value that will cause us trouble.
Add 1 to that negative value before negating it.
To compensate for that I multiplicate the base once more separately.
if (n == -2,147,483,648)
{
return (1.0/x) * myPow(1.0/x, -(n + 1));
}
The full solution
double myPow(double x, int n)
{
if (n == 0) return 1.0;
if (n < 0)
{
if (n == -2,147,483,648)
{
return (1.0/x) * myPow(1.0/x, -(n + 1));
}
return myPow(1.0/x, -n);
}
return (n % 2 == 0) ? myPow(x * x, n / 2) : x * myPow(x * x, n / 2);
}
Find below my implementation for binary exponentiation
#include<iostream>
#include<cmath>
using namespace std;
int fast_exponentiation(int base, int pow) {
unsigned int result; // variable to store intermediaries
if (pow == 1) {
return base;
}
else if (pow == 0) {
return 1;
}
result = fast_exponentiation(base, floor(pow/2));
// even power
if (pow % 2 == 0) {
return result * result;
}
// odd power
else {
return result * base * result;
}
}
int main() {
int num, answer, p;
cout << "Enter the base: ";
cin >> num;
cout << "Enter power: ";
cin >> p;
answer = fast_exponentiation(num, p);
cout << answer << endl;
return 0;
}
The problem is when I ran this for inputs num= 3 and pow = 20 I get -808182895, a negative number. I can't seem to figure out what is wrong with the code? Can I get some help?
Value of 3^20 exceeds max possible int value 2^31, so you have got overflow. The simplest way to overcome this limit is using long long data type to provide possiblity for calculations upto power 39 (near 2^63)
For larger powers one need long number arithmetics - boost multi-precision, GMP etc
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);
}
Im trying to make a function that does division with out the / symbol
long q(int nm1, int nm2)
{
long q = 0;
while ( num1 > num2)
{
some subtraction here
}
return q;
}
the idea is to assume the input is in order and the first is to be divided by the second.
This means subtract the second from the first until the second is less then the first number.
I tried many different ways to do this but for what ever reason I cant hit it.
For now I am assuming the number is positive and wont return division by zero (I can fix that later by calling my other functions)
This means subtract the the second from the first until the second is less than the first number.
And what's the problem with that?
int div(int num, int den)
{
int frac;
for (frac = 0; num >= den; num -= den, frac++)
;
return frac;
}
What you're original post is trying to do is the Division by repeated subtraction algorithm. Have a look at Wikipedia:
The simplest division algorithm, historically incorporated into a
greatest common divisor algorithm presented in Euclid's Elements, Book
VII, Proposition 1, finds the remainder given two positive integers
using only subtractions and comparisons
while N ≥ D do
N := N - D
end
return N
Just add a counter in your while loop to keep track of the number of iterations (which is what you will want to return) and after your loop N will contain your remainder (if it is not 0 of course).
This code will work only if the num and den are integer values.
int main( int num, int den )
{
if(den==0)
{
return 1;
}
else
{
while(num!=0)
{
num = num - den;
}
}
return 0;
}
Just improving the above answer slightly.
Use modulus
long div(int num, int den)
{
int frac;
int num2 = num;
for (frac = 0; num2 >= den; num2 -= den, frac++)
;
// i needed the original num and den.
return ( (long) frac )+( num % den );
// casts frac to long then adds the modulus remainder of the values.
}
just a bit optimization: you don't want to have linear time complexity with the input value
int div(int num, int den)
{
int result = 0;
int i;
long long x;
long long y;
if (num < 0) return -div(-num, den);
if (den < 0) return -div(num, den);
if (num < den) return 0;
x = num;
y = den;
i = 0;
while((i < 32) && (x > (y << (i+1)))) i++;
for(;i>0; i++)
{
if (x > (y << i))
{
x -= y;
result += 1 << i;
}
}
return result;
}