I have two functions here that together compute the nCr:
int factorial(int n) {
int c;
int result = 1;
for (c = 1; c <= n; c++)
{
result = result*c;
}
return result;
}
int nCr(int n, int r) {
int result;
result = factorial(n)/(factorial(r)*factorial(n-r));
return result;
}
I am having trouble with an error check I need to implement. As n gets larger, I won't have the ability to computer n! and this error check has to exist in both nCr and factorial. They both must detect this overflow.
Currently, when I enter a number that is too large for computation, I get a floating type error returned from the command line.
I am having trouble accounting for this overflow check. Any help would be much appreciated, thanks.
A better way of calculating binomial coefficients
typedef unsigned long long ull;
ull nCr(int n, int r) {
ull res = 1;
if (r > n - r) r = n - r;
for (int i = 0; i < r; ++i) {
res *= (n - i);
res /= (i + 1);
}
return res;
}
In your code, the maximum value is always factorial(n),
so you only need to check that n! isn't bigger than 2.147.483.647 (max int value).
Please note that the stored max value can be different based on the size of the int type in memory (different machines can specify different sizes).
However, the last bit in int type variables is reserved for storing the sign (+ or -), thus the max value can be half of 65.535 and 4.294.967.295 i.e. 32.767 and 2.147.483.647 for int types.
SIZE_OF_INT(bits) MAX VALUE(UNSIGNED) MAX_VALUE(SIGNED)
---------------------------------------------------------------
16 65.535 32.767
32 4.294.967.295 2.147.483.647
The value of 13! can go beyond the max value of the int type (in 32 bit).
12! = 479.001.600 and
13! = 6.227.020.800
So, you need to check in nCr(int n, int r) that the max value of n is always less than 13 (i.e. n<=12) and r<=n.
And in factorial(int n): n<=12.
Related
I am trying to calculate 100! (that is, the factorial of 100).
I am looking for the simplest way to accomplish this using C. I have read around but have not found a concrete answer.
If you must know, I program in Xcode in Mac os X.
If you're looking for a simple library, libtommath (from libtomcrypt) is probably what you want.
If you're looking to write a simple implementation yourself (either as a learning exercise or because you only need a very limited subset of bigint functionality and don't want to tack on a dependency to a large library, namespace pollution, etc.), then I might suggest the following for your problem:
Since you can bound the size of the result based on n, simply pre-allocate an array of uint32_t of the required size to hold the result. I'm guessing you'll want to print the result, so it makes sense to use a base that's a power of 10 (i.e. base 1000000000) rather than a power of 2. That is to say, each element of your array is allowed to hold a value between 0 and 999999999.
To multiply this number by a (normal, non-big) integer n, do something like:
uint32_t carry=0;
for(i=0; i<len; i++) {
uint64_t tmp = n*(uint64_t)big[i] + carry;
big[i] = tmp % 1000000000;
carry = tmp / 1000000000;
}
if (carry) big[len++] = carry;
If you know n will never be bigger than 100 (or some other small number) and want to avoid going into the 64-bit range (or if you're on a 64-bit platform and want to use uint64_t for your bigint array), then make the base a smaller power of 10 so that the multiplication result will always fit in the type.
Now, printing the result is just something like:
printf("%lu", (long)big[len-1]);
for(i=len-1; i; i--) printf("%.9lu", (long)big[i-1]);
putchar('\n');
If you want to use a power of 2 as the base, rather than a power of 10, the multiplication becomes much faster:
uint32_t carry=0;
for(i=0; i<len; i++) {
uint64_t tmp = n*(uint64_t)big[i] + carry;
big[i] = tmp;
carry = tmp >> 32;
}
if (carry) big[len++] = carry;
However, printing your result in decimal will not be so pleasant... :-) Of course if you want the result in hex, then it's easy:
printf("%lx", (long)big[len-1]);
for(i=len-1; i; i--) printf("%.8lx", (long)big[i-1]);
putchar('\n');
Hope this helps! I'll leave implementing other things (like addition, multiplication of 2 bigints, etc) as an exercise for you. Just think back to how you learned to do base-10 addition, multiplication, division, etc. in grade school and teach the computer how to do that (but in base-10^9 or base-2^32 instead) and you should have no problem.
If you're willing to use a library implementation the standard one seems to be GMP
mpz_t out;
mpz_init(out);
mpz_fac_ui(out,100);
mpz_out_str(stdout,10,out);
should calculate 100! from looking at the docs.
You asked for the simplest way to do this. So, here you go:
#include <gmp.h>
#include <stdio.h>
int main(int argc, char** argv) {
mpz_t mynum;
mpz_init(mynum);
mpz_add_ui(mynum, 100);
int i;
for (i = 99; i > 1; i--) {
mpz_mul_si(mynum, mynum, (long)i);
}
mpz_out_str(stdout, 10, mynum);
return 0;
}
I tested this code and it gives the correct answer.
You can also use OpenSSL bn; it is already installed in Mac OS X.
You can print factorial 1000 in C with just 30 lines of code, <stdio.h> and char type :
#include <stdio.h>
#define B_SIZE 3000 // number of buffered digits
struct buffer {
size_t index;
char data[B_SIZE];
};
void init_buffer(struct buffer *buffer, int n) {
for (buffer->index = B_SIZE; n; buffer->data[--buffer->index] = (char) (n % 10), n /= 10);
}
void print_buffer(const struct buffer *buffer) {
for (size_t i = buffer->index; i < B_SIZE; ++i) putchar('0' + buffer->data[i]);
}
void natural_mul_buffer(struct buffer *buffer, const int n) {
int a, b = 0;
for (size_t i = (B_SIZE - 1); i >= buffer->index; --i) {
a = n * buffer->data[i] + b;
buffer->data[i] = (char) (a % 10);
b = a / 10;
}
for (; b; buffer->data[--buffer->index] = (char) (b % 10), b /= 10);
}
int main() {
struct buffer number_1 = {0};
init_buffer(&number_1, 1);
for (int i = 2; i <= 100; ++i)
natural_mul_buffer(&number_1, i);
print_buffer(&number_1);
}
You will find faster but the “little” factorial(10000) is here computed ≈ instantly.
You can put it into a fact.c file then compile + execute :
gcc -O3 -std=c99 -Wall -pedantic fact.c ; ./a.out ;
If you want to execute some base conversion there is a solution, see also Fibonacci(10000), Thank You.
I working through a book on C on my own. This isn't homework to be turned in. I am writing a C program to determine the largest Fibonacci number my machine can produce. And instructed to use a nonrecursive method.
My Code:
#include<stdio.h>
double fibo(int n);
int main(void)
{
int n = 0; // The number input by the user
double value; // Value of the series for the number input
while (n >= 0)
{
// Call fibo function
value = fibo(n);
// Output the value
printf("For %d the value of the fibonacci series = %.0f\n", n,
value);
n++;
}
return 0;
}
double fibo(int n)
{
int i; // For loop control variable
double one = 0; // First term
double two = 1; // Second term
double sum = 0; // placeholder
if (n == 0)
return 0;
else if (n == 1)
return 1;
else
{
for (i = 2; i <= n; i++)
{
sum = one + two;
one = two;
two = sum;
}
}
return sum;
Code works fine but I want to to break when the output gives me the fist instance of :
For 17127 the value of the fibonacci series = inf
Is there way to us an if statement like:
if (value == inf)
break;
The simplest is to use INFINITY or isinf().
Just did a little search and found this nice trick:
...
double value, temp; // Value of the series for the number input
while (n >= 0)
{
// Call fibo function
temp = fibo(n);
if (temp - temp != 0)
break;
else
value=temp;
...
well it turns out that whats happening is when temp hits Inf the if condition temp - temp produces Nan which equals nothing and the rest is just executing break; to exit the process.
I want to to break when the output gives me the first instance of : inf
Simply test against INFINITY from <math.h>. The output will not be an exact Fibonacci number.
#include <math.h>
#include <stdio.h>
int main(void) {
double a;
double b = 0;
double c = 1;
do {
a = b;
b = c;
c = a + b;
} while (c < INFINITY);
printf("%e\n", b);
return 0;
}
Output
1.306989e+308
long double
Use the widest floating point type and look for an inexact addition.
#include <fenv.h>
#include <stdio.h>
int main(void) {
long double a;
long double b = 0;
long double c = 1;
do {
a = b;
b = c;
c = a + b;
} while (fetestexcept(FE_INEXACT) == 0);
printf("%.0Lf\n", b);
return 0;
}
Output
12200160415121876738
Integers
Use the widest type available. This is akin to #Syed.Waris unsigned long long approach. Although common that unsigned long long and uintmax_t have the same range, using uintmax_t insures the widest.
uintmax_t: The following type designates an unsigned integer type capable of representing any value of any unsigned integer type:
#include <stdint.h>
#include <stdio.h>
uintmax_t a;
uintmax_t b = 0;
uintmax_t c = 1;
do {
a = b;
b = c;
c = a + b;
} while(c >= b);
printf("%ju\n", b);
Output
12200160415121876738
String
An alternative to double or some int type, is to create a simple string add function str_add(), then quite easy to form large Fibonacci numbers.
int main(void) {
char fib[3][4000];
strcpy(fib[0], "0");
strcpy(fib[1], "1");
int i;
for (i = 2; i <= 17127 && strlen(fib[1]) < sizeof fib[1] - 1; i++) {
printf("Fib(%3d) %s.\n", i, str_add(fib[2], fib[1], fib[0]));
strcpy(fib[0], fib[1]);
strcpy(fib[1], fib[2]);
}
printf("%zu\n", strlen(fib[2]));
return 0;
}
Output
Fib(1476) 13069...(299 digits)....71632. // Exact max `double`
Fib(17127) 95902...(3569 digits)...90818.
largest Fibonacci number my machine can produce
This question is not concerned with any data type but it is concerned with machine.
The basic rule of fibonacci is this:
n = (n-1) + (n-2)
You can take a big sized unsigned long long variable and you can keep on adding. But what if that datatype is overflowed? You are not concerned with data type. Your machine may produce a number even bigger than the long long. What would that number be ? Entire bits on RAM? Hard Disk ?
Since you are required to use an iterative method and not recursive method, your teacher/book/instructor might be testing you on loops (and not any standard API). Below is sample code using unsigned long long:
#include <stdio.h>
int main ()
{
unsigned long long a = 0;
unsigned long long b = 1;
unsigned long long c = a + b;
while(c >= b)
{
a = c;
c = b + c;
b = a;
}
printf("\n%llu\n", b);
return 0;
}
Output:
12200160415121876738
Hey everyone of Stack Overflow!
So I am stuck on this prompt:
"Use a loop to determine the value of n that will produce the largest n! value that could be stored in an unsigned short variable. Print out the maximum value for an unsigned short variable, the value of n that will produce the largest n! that is less than or equal to the maximum value for an unsigned short variable. NOTE: The constant USHRT_MAX contained in limits.h provides the maximum value for an unsigned short variable."
I'm guessing, for the above prompt, that it addresses why when I enter an integer such as 34 into the program, I get 0 as the output for the factorial of 34.
I have already made the code for determining the n! value when n is entered so far, but this new part has me confused.
I don't think this will help, but here is the code I have before this prompt:
#include <stdio.h>
unsigned long Factorial(unsigned int n);
int main(void)
{
int num[11],i=0,factorials[11];
printf("Please enter up to 10 integers (q to quit): ");
//Ask for integers until a 'q' is entered and store integer values entered into array 'num'
while (scanf("%u",&num[i]))
{
//Store the factorial of integers entered into array 'factorials'
factorials[i]=Factorial(num[i]);
//Print numbers out in a two column table
printf("%5u %9u\n",num[i],factorials[i]);
i++;
}
return 0;
}
//Calculates the factorial of 'n'
unsigned long Factorial(unsigned int n)
{
int nFactorial,i=1;
nFactorial=n;
while (i<n)
{
nFactorial=nFactorial*i;
i++;
}
n=nFactorial;
}
Anyways, if anyone can help out, I'd greatly appreciate it! I know this sounds like a tall order of a question, so even a pointer would help heaps!
Thanks anyone!
Cheers, Will.
EDIT: I apologize in advance if my code is difficult to read, I'm working on making it better
EDIT:
I came up with this to answer the prompt so far, but it doesn't seem right. The output value is 8...
//Detemine largest max value of n
for (i=0;Factorial(i)<=USHRT_MAX;i++);
printf("The max value for an unsigned short is %u\n Max value of n: %u\n",USHRT_MAX,i-1);
return 0;
Since you're using a short, you can store the factorial sum in a larger type like unsigned long int.
int main(void)
{
unsigned long int sum = 1;
unsigned int n;
for( n = 1; sum < USHRT_MAX; n++ ) {
sum *=n;
}
printf("%lu\n", sum);
printf("%u\n", n);
}
This is kind of cheating as there's no guarantee a long int will be larger than a short, but it's really likely. You can mitigate that by verifying.
assert( sizeof(unsigned short) < sizeof(unsigned long int) );
The non-cheating way is to check if you're about to overflow. You're gonna want to do this, but you can't.
USHRT_MAX >= sum * n
sum * n will overflow. Instead, divide both sides by n and check that.
USHRT_MAX / n >= sum
That will stop just before sum *= n would overflow. We can verify by plugging in some numbers. USHRT_MAX = 23, n = 4 and sum = 6...
23 / 4 >= 6
5 >= 6
Note that this is integer division, so it's truncated. That's fine for our purposes.
#include <stdio.h>
#include <limits.h>
int main(void)
{
unsigned short sum = 1;
unsigned int n;
for( n = 1; (USHRT_MAX / n) >= sum; n++ ) {
sum *=n;
}
// We went one too far
n--;
printf("%u\n", sum);
printf("%u\n", n);
}
The function calculates the value of sinh(x) using the following
development in a Taylor series:
I want to calculate the value of sinh(3) = 10.01787, but the function outputs 9. I also get this warning:
1>main.c(24): warning C4244: 'function': conversion from 'double' to 'int', possible loss of data
This is my code:
int fattoriale(int n)
{
int risultato = 1;
if (n == 0)
{
return 1;
}
for (int i = 1; i < n + 1; i++)
{
risultato = risultato * i;
}
return risultato;
}
int esponenziale(int base, int esponente)
{
int risultato = 1;
for (int i = 0; i < esponente; i++)
{
risultato = risultato * base;
}
return risultato;
}
double seno_iperbolico(double x)
{
double risultato = 0, check = -1;
for (int n = 0; check != risultato; n++)
{
check = risultato;
risultato = risultato + (((esponenziale(x, ((2 * n) + 1))) / (fattoriale((2 * n) + 1))));
}
return risultato;
}
int main(void)
{
double numero = 1;
double risultato = seno_iperbolico(numero);
}
Please help me fix this program.
It is actually pretty great that the compiler is warning you about this kind of data loss.
You see, when you call this:
esponenziale(x, ((2 * n) + 1))
You essentially lose your accuracy since you are converting your double, which is x, to an int. This is since the signature of esponenziale is int esponenziale(int base, int esponente).
Change it to double esponenziale(double base, int esponente), risultato should be a double as well, since you are returning it from the function and performing mathematical operations with/on it.
Remember that dividing a double with an int gives you a double back.
Edit: According to ringø's comment, and seeing how it actually solved your issue, you should also set double fattoriale(int n) and inside that double risultato = 1;.
You are losing precision since many of the terms will be fractional quantities. Using an int will clobber the decimal portion. Replace your int types with double types as appropriate.
Your factorial function will overflow for surprisingly small values of n. For 16 bit int, the largest value of n is 7, for 32 bit it's 12 and for 64 bit it's 19. The behaviour on overflowing a signed integral type is undefined. You could use unsigned long long or a uint128_t if your compiler supports it. That will buy you a bit more time. But given you're converting to a double anyway, you may as well use a double from the get-go. Note that an IEEE764 floating point double will hit infinity at 171!
Be assured that the radius of convergence of the Maclaurin expansion of sinh is infinite for any value of x. So any value of x will work, although convergence might be slow. See http://math.cmu.edu/~bkell/21122-2011f/sinh-maclaurin.pdf.
Tried to develop a code that quickly finds Fibonacci values.
But the problem is I get SIGSEGV error when input is of order 1000000.
Also from other questions around here I came to know that it may be because of stack memory that exceeds limit during runtime. And I guess that is the case here.
#include<stdio.h>
unsigned long long int a[1000001] = {0};
unsigned long long int fib(int n)
{
unsigned long long int y;
if(n==1 || n==0)
return n;
if (a[n] != 0)
return a[n];
else
{
y=fib(n-1)+fib(n-2);
a[n] = y;
}
return y;
}
main()
{
int N;
unsigned long long int ans;
a[0] = 1;
a[1] = 1;
scanf(" %d",&N);
ans = fib(N+1);
printf("%llu",ans);
}
How do I fix this code for input value of 1000000?
Here's a better approach (which can still be significantly improved) that will calculate Fibonacci numbers for you:
unsigned long long Fibonacci(int n)
{
unsigned long long last[2] = { 0, 1 }; // the start of our sequence
if(n == 0)
return 0;
for(int i = 2; i <= n; i++)
last[i % 2] = last[0] + last[1];
return last[n % 2];
}
However, you are not going to be able to calculate the millionth Fibonacci number with it, because that number is much, much, much, much larger than the largest number that can fit in an unsigned long long.
Instead of using the stack, use your own variables to track state. Essentially, do the function calls and returns with your own code.
The best way really is just to switch the algorithm entirely to one that's efficient. For example, to calculate fib(6), your code calculates fib(4) twice, once when fib(5) asks and once when fib(6) asks.