I'm trying to write a C program which performs multiplication of two numbers without directly using the multiplication operator, and it should take into account numbers which are sufficiently large so that even the usual addition of these two numbers cannot be performed by direct addition.
I was motivated for this when I was trying to (and successfully did) write a C program which performs addition using character strings, I did the following:
#include<stdio.h>
#define N 100000
#include<string.h>
void pushelts(char X[], int n){
int i, j;
for (j = 0; j < n; j++){
for (i = strlen(X); i >= 0; i--){
X[i + 1] = X[i];
}
X[0] = '0';
}
}
int max(int a, int b){
if (a > b){ return a; }
return b;
}
void main(){
char E[N], F[N]; int C[N]; int i, j, a, b, c, d = 0, e;
printf("Enter the first number: ");
gets_s(E);
printf("\nEnter the second number: ");
gets_s(F);
a = strlen(E); b = strlen(F); c = max(a, b);
pushelts(E, c - a); pushelts(F, c - b);
for (i = c - 1; i >= 0; i--){
e = d + E[i] + F[i] - 2*'0';
C[i] = e % 10; d = e / 10;
}
printf("\nThe answer is: ");
for (i = 0; i < c; i++){
printf("%d", C[i]);
}
getchar();
}
It can add any two numbers with "N" digits. Now, how would I use this to perform multiplication of large numbers? First, I wrote a function which performs the multiplication of number, which is to be entered as a string of characters, by a digit n (i.e. 0 <= n <= 9). It's easy to see how such a function is written; I'll call it (*). Now the main purpose is to multiply two numbers (entered as a string of characters) with each other. We might look at the second number with k digits (assuming it's a1a2.....ak) as:
a1a2...ak = a1 x 10^(k - 1) + a2 x 10^(k - 2) + ... + ak-1 x 10 + ak
So the multiplication of the two numbers can be achieved using the solution designed for addition and the function (*).
If the first number is x1x2.....xn and the second one is y1y2....yk, then:
x1x2...xn x y1y2...yk = (x1x2...xn) x y1 x 10^(k-1) + .....
Now the function (*) can multiply (x1x2...xn) with y1 and the multiplication by 10^(k-1) is just adding k-1 zero's next to the number; finally we add all of these k terms with each other to obtain the result. But the difficulty lies in just knowing how many digits each number contains in order to perform the addition each time inside the loop designed for adding them together. I have thought about doing a null array and each time adding to it the obtained result from multiplication of (x1x2....xn) by yi x 10^(i-1), but like I've said I am incapable of precising the required bounds and I don't know how many zeros I should each time add in front of each obtained result in order to add it using the above algorithm to the null array. More difficulty arises when I'll have to do several conversions from char types into int types and conversely. Maybe I'm making this more complicated than it should; I don't know if there's an easier way to do this or if there are tools I'm unaware of. I'm a beginner at programming and I don't know further than the elementary tools.
Does anyone have a solution or an idea or an algorithm to present? Thanks.
There is an algorithm for this which I developed when doing Small Factorials problem on SPOJ.
This algorithm is based on the elementary school multiplication method. In school days we learn multiplication of two numbers by multiplying each digit of the first number with the last digit of the second number. Then multiplying each digit of the first number with second last digit of the second number and so on as follows:
1234
x 56
------------
7404
+6170- // - is denoting the left shift
------------
69104
What actually is happening:
num1 = 1234, num2 = 56, left_shift = 0;
char_array[] = all digits in num1
result_array[]
while(num2)
n = num2%10
num2 /= 10
carry = 0, i = left_shift, j = 0
while(char_array[j])
i. partial_result = char_array[j]*n + carry
ii. partial_result += result_array[i]
iii. result_array[i++] = partial_result%10
iv. carry = partial_result/10
left_shift++
Print the result_array in reverse order.
You should note that the above algorithm work if num1 and num2 do not exceed the range of its data type. If you want more generic program, then you have to read both numbers in char arrays. Logic will be the same. Declare num1 and num2 as char array. See the implementation:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char num1[200], num2[200];
char result_arr[400] = {'\0'};
int left_shift = 0;
fgets(num1, 200, stdin);
fgets(num2, 200, stdin);
size_t n1 = strlen(num1);
size_t n2 = strlen(num2);
for(size_t i = n2-2; i >= 0; i--)
{
int carry = 0, k = left_shift;
for(size_t j = n1-2; j >= 0; j--)
{
int partial_result = (num1[j] - '0')*(num2[i] - '0') + carry;
if(result_arr[k])
partial_result += result_arr[k] - '0';
result_arr[k++] = partial_result%10 + '0';
carry = partial_result/10;
}
if(carry > 0)
result_arr[k] = carry +'0';
left_shift++;
}
//printf("%s\n", result_arr);
size_t len = strlen(result_arr);
for(size_t i = len-1; i >= 0; i-- )
printf("%c", result_arr[i]);
printf("\n");
}
This is not a standard algorithm but I hope this will help.
Bignum arithmetic is hard to implement efficiently. The algorithms are quite hard to understand (and efficient algorithms are better than the naive one you are trying to implement), and you could find several books on them.
I would suggest using an existing Bignum library like GMPLib or use some language providing bignums natively (e.g. Common Lisp with SBCL)
You could re-use your character-string-addition code as follows (using user300234's example of 384 x 56):
Set result="0" /* using your character-string representation */
repeat:
Set N = ones_digit_of_multiplier /* 6 in this case */
for (i = 0; i < N; ++i)
result += multiplicand /* using your addition algorithm */
Append "0" to multiplicand /* multiply it by 10 --> 3840 */
Chop off the bottom digit of multiplier /* divide it by 10 --> 5 */
Repeat if multiplier != 0.
Related
Program not working, not giving output, I don't know what to do, where the problem is.
I'm trying to find out the largest palindrome made from the product of two 3-digit numbers.
#include <stdio.h>
main() {
int i, k, j, x;
long int a[1000000], palindrome[1000000], great, sum = 0;
// for multiples of two 3 digit numbers
for (k = 0, i = 100; i < 1000; i++) {
for (j = 100; j < 1000; j++) {
a[k] = i * j; // multiples output
k++;
}
}
for (i = 0, x = 0; i < 1000000; i++) {
// for reverse considered as sum
for (; a[i] != 0;) {
sum = sum * 10 + a[i] % 10;
}
// for numbers which are palindromes
if (sum == a[i]) {
palindrome[x] = a[i];
x++;
break;
}
}
// comparison of palindrome number for which one is greatest
great = palindrome[0];
for (k = 0; k < 1000000; k++) {
if (great < palindrome[k]) {
great = palindrome[k];
}
}
printf("\ngreatest palindrome of 3 digit multiple is : ", great);
}
What do you mean with "not working"?
There are two things, from my point of view:
1) long int a[1000000], palindrome[1000000]
Depending on you compile configuration you could have problems compiling your code.
Probably the array is too big to fit in your program's stack address space.
In C or C++ local objects are usually allocated on the stack. Don't allocate it local on stack, use some other place instead. This can be achieved by either making the object global or allocating it on the global heap.
#include <stdio.h>
long int a[1000000], palindrome[1000000], great, sum = 0;
main() {
int i, k, j, x;
2) printf("\ngreatest palindrome of 3 digit multiple is : ", great);
I will change it by :
printf("\ngreatest palindrome of 3 digit multiple is %li: ", great);
Regards.
Compiling and running your code on an on-line compiler I got this:
prog.c:3:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
main() {
^
prog.c:34:61: warning: data argument not used by format string [-Wformat-extra-args]
printf("\ngreatest palindrome of 3 digit multiple is : ", great);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^
2 warnings generated.
Killed
Both the warnings should be taken into account, but I'd like to point out the last line. The program was taking too much time to run, so the process was killed.
It's a strong suggestion to change the algorithm, or at least to fix the part that checks if a number is a palindrome:
for (; a[i] != 0;) { // <-- If a[i] is not 0, this will never end
sum = sum * 10 + a[i] % 10;
}
I'd use a function like this one
bool is_palindrome(long x)
{
long rev = 0;
for (long i = x; i; i /= 10)
{
rev *= 10;
rev += i % 10;
}
return x == rev;
}
Also, we don't need any array, we could just calculate all the possible products between two 3-digits number using two nested for loops and check if those are palindromes.
Starting from the highest numbers, we can store the product, but only if it's a palindrome and is bigger than any previously one found, and stop the iteration of the inner loop as soon as the candidate become less then the stored maximum. This would save us a lot of iterations.
Implementing this algorithm, I found out a maximum value of 906609.
I am trying to solve this: SPOJ problem.
And after some research I found out that it comes down to a simple calculation of the nth fib number, however n can get really large so an O(n) solution won't do any good. Googling around, I found that you can calculate the nth fib number in O(logn) and also a code sample that does exactly that:
long long fibonacci(int n) {
long long fib[2][2] = {{1,1},{1,0}}, ret[2][2] = {{1,0},{0,1}}, tmp[2][2] = {{0,0},{0,0}};
int i, j, k;
while (n) {
if (n & 1) {
memset(tmp, 0, sizeof tmp);
for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++)
for (k = 0; k < 2; k++)
tmp[i][j] = (tmp[i][j] + ret[i][k] * fib[k][j]);
for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++)
ret[i][j] = tmp[i][j];
}
memset(tmp, 0, sizeof tmp);
for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++)
for (k = 0; k < 2; k++)
tmp[i][j] = (tmp[i][j] + fib[i][k] * fib[k][j]);
for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++)
fib[i][j] = tmp[i][j];
n /= 2;
}
return (ret[0][1]);
}
I tried to modify it for the problem and am still getting WA: http://ideone.com/3TtE5m
Am I calculating the modular arithmetic wrong? Or is something else the issue?
You mean the nth Fibonacci number I hope.
In order to do it you need a matrix decomposition of Fibonacci numbers described here.
The basic idea is you take the Donald E. Knuth matrix identity form for a Fibonacci number which is:
And instead of calculating the Fibonacci numbers in the traditional way you will try and find the matrix to the power of (k) where k is the given number.
So this is solving the problem in k matrix multiplications, not really helpful since we can do it in much easier way.
But wait! We can optimise the matrix multiplication. Instead of doing the k multiplications we can square it first and then do the half of the multiplications. And we can keep on doing it. So if the given number is 2a then we can do it in a steps. By keeping squaring the matrix.
If the number is not a power of 2 we can do the binary decomposition of a number and see whether to take the given squared matrix into final product or not.
In your case after each multiplication you also need to apply modulo operator 123456 to each matrix element.
Hope my explanation helps if not see the link for a clearer and longer one.
There is actually one more caveat of the task: as you are asked to provide some Fibonacci number modulo a given number, you should also prove that taking the remainder of each matrix element doesn't change the result. In other words if we multiply matrices and take remainder that we are actually still getting the Fibonacci number remainders. But since the remainder operation is distributive in addition and multiplication it actually does produce the correct results.
The Fibonacci numbers occur as the ratio of successive convergents of the continued fraction for , and the matrix formed from successive convergents of any continued fraction has a determinant of +1 or −1.
The matrix representation gives the following closed-form expression for the Fibonacci numbers i.e.
The matrix is multiplied n time because then only we can get the (n+1)th Fibonacci number as the element at the row and the column (0, 0) in the resultant matrix.
If we apply the above method without using recursive matrix multiplication, then the Time Complexity: O(n) and Space Complexity: O(1).
But we want Time Complexity: O(log n), so we have to optimize the above method, and this can be done by recursive multiplication of matrix to get the nth power.
Implementation of the above rule can be found below.
#include <stdio.h>
void multiply(int F[2][2], int M[2][2]);
void power(int F[2][2], int n);
/*
The function that returns nth Fibonacci number.
*/
int fib(int n) {
int F[2][2] = {{1, 1}, {1, 0}};
if (n == 0)
return 0;
power(F, n - 1);
return F[0][0];
}
/*
Optimized using recursive multiplication.
*/
void power(int F[2][2], int n) {
if ( n == 0 || n == 1)
return;
int M[2][2] = {{1, 1}, {1, 0}};
power(F, n / 2);
multiply(F, F);
if (n % 2 != 0)
multiply(F, M);
}
void multiply(int F[2][2], int M[2][2]) {
int x = F[0][0] * M[0][0] + F[0][1] * M[1][0];
int y = F[0][0] * M[0][1] + F[0][1] * M[1][1];
int z = F[1][0] * M[0][0] + F[1][1] * M[1][0];
int w = F[1][0] * M[0][1] + F[1][1] * M[1][1];
F[0][0] = x;
F[0][1] = y;
F[1][0] = z;
F[1][1] = w;
}
int main() {
printf("%d\n", fib(15));
/*
15th Fibonacci number is 610.
*/
return 0;
}
There is a very simple algorithm, using only integers:
long long fib(int n) {
long long a, b, p, q;
a = q = 1;
b = p = 0;
while (n > 0) {
if (n % 2 == 0) {
long long qq = q*q;
q = 2*p*q + qq;
p = p*p + qq;
n /= 2;
} else {
long long aq = a*q;
a = b*q + aq + a*p;
b = b*p + aq;
n -= 1;
}
}
return b;
}
This is based on the identities of the Lucas sequence.
First of all, I searched and all questions I found are similar but not exactly this one.
This is my first post here, I'm a beginner in programming and currently learning to code in C.
Been struggling with this code for about 5 hours now.
The question is create a program in C, using only loops (and not using pow(), using stdio.h library only).
The question is to get the user to give you two numbers - X and N
the program will print The result of the following equation:
1+2x+3x^2+4x^3+....+nx^(n-1)
For example for the input of - X=2 N=3
1*2^0 + 2*2^1 + 3*2^2
What the program will print is "17"
This is my attempt so far, I got to the Power function but I cant find a way to incorporate into the programm itself.
#include <stdio.h>
int main(void)
{
int i, j=0, b = 0;
float x, n;
double sum = 0, sumt=0;
do{
printf("Please enter two numbers \n");
flushall;
scanf("%f %f", &n, &x);
} while (x <= 0);
for (i = 1; i <= n; i++){
sum = x*x;
}
sumt += sum;
printf("%f", sum);
}
Instead of trying to create an implementation of pow, you will need to take advantage of the relationship between the terms of the expression.
The n-th term is nx^(n-1). The n-1-the term is (n-1)x^(n-2).
If we denote the n-th term as T(n) and denote the n-1-th term as T(n-1),
T(n) = T(n-1)*x*n/(n-1)
Given the starting value of the first term,
T(1) = 1
you can compute the subsequent terms using the above formula.
The following code should work.
// Initialize the values for N=1
term = 1;
sum = 1;
// Iterate starting from 2
for (i = 2; i <= n; i++){
term *= x*i/(i-1);
sum += term;
}
The working Program based on the tips given by the almighty #R_Sahu (And others ;D)
**
#include <stdio.h>
int main(void)
{
int i, j = 0, c = 0;
float x, n, b = 0;
double term, sum;
do {
printf("Enter Two Numbers\n");
flushall;
scanf("%f%f", &n, &x);
} while (x < 0);
for (i = 2; i < n + 2; i++)
{
term = 1;
sum = 1;
for (i = 2; i <= n; i++){
term *= x*i / (i - 1);
sum += term;
}
}
printf("The answer is %.lf ", sum);
}
I will not give you the code, but the reasoning you should follow
First you have to somehow get the data from the user (as a parameter, from stdio... whatever)
x = getFromUser
n = getFromUser
You will then need to init a temporary result
result = 0
How many times do you have to add? -> Exactly n times
for(ii=0;ii<n;ii++) {
result = result + pow((ii*x),(ii-1)) //There is something missing here, I'll let you guess what
}
But wait; you cannot use pow. So you have to program it by yourself (I guess that's the idea of the exercise)
then you need a function, and it has to return an int (actually, it may return even irrational numbers, but I don't think they will require you to do that)
int customPow(int base, int exponent) {
//Put your for in here, and may the pow be with you
}
You need to figure out the code yourself, but the general idea is as follows:
Create your own pow function which returns x*n.
int pow(int x, int n){
//use a for or while loop to calculate x (*x)n times.
//pay attention to the base cases (i.e., when n = 0, or 1 etc)
}
ans = 0;
for(i = 0 to N-1){
ans = ans + pow(x,i-1)*i;
}
Could you explain me how the following two algorithms work?
int countSort(int arr[], int n, int exp)
{
int output[n];
int i, count[n] ;
for (int i=0; i < n; i++)
count[i] = 0;
for (i = 0; i < n; i++)
count[ (arr[i]/exp)%n ]++;
for (i = 1; i < n; i++)
count[i] += count[i - 1];
for (i = n - 1; i >= 0; i--)
{
output[count[ (arr[i]/exp)%n] - 1] = arr[i];
count[(arr[i]/exp)%n]--;
}
for (i = 0; i < n; i++)
arr[i] = output[i];
}
void sort(int arr[], int n)
{
countSort(arr, n, 1);
countSort(arr, n, n);
}
I wanted to apply the algorithm at this array:
After calling the function countSort(arr, n, 1) , we get this:
When I call then the function countSort(arr, n, n) , at this for loop:
for (i = n - 1; i >= 0; i--)
{
output[count[ (arr[i]/exp)%n] - 1] = arr[i];
count[(arr[i]/exp)%n]--;
}
I get output[-1]=arr[4].
But the array doesn't have such a position...
Have I done something wrong?
EDIT:Considering the array arr[] = { 10, 6, 8, 2, 3 }, the array count will contain the following elements:
what do these numbers represent? How do we use them?
Counting sort is very easy - let's say you have an array which contains numbers from range 1..3:
[3,1,2,3,1,1,3,1,2]
You can count how many times each number occurs in the array:
count[1] = 4
count[2] = 2
count[3] = 3
Now you know that in a sorted array,
number 1 will occupy positions 0..3 (from 0 to count[1] - 1), followed by
number 2 on positions 4..5 (from count[1] to count[1] + count[2] - 1), followed by
number 3 on positions 6..8 (from count[1] + count[2] to count[1] + count[2] + count[3] - 1).
Now that you know final position of every number, you can just insert every number at its correct position. That's basically what countSort function does.
However, in real life your input array would not contain just numbers from range 1..3, so the solution is to sort numbers on the least significant digit (LSD) first, then LSD-1 ... up to the most significant digit.
This way you can sort bigger numbers by sorting numbers from range 0..9 (single digit range in decimal numeral system).
This code: (arr[i]/exp)%n in countSort is used just to get those digits. n is base of your numeral system, so for decimal you should use n = 10 and exp should start with 1 and be multiplied by base in every iteration to get consecutive digits.
For example, if we want to get third digit from right side, we use n = 10 and exp = 10^2:
x = 1234,
(x/exp)%n = 2.
This algorithm is called Radix sort and is explained in detail on Wikipedia: http://en.wikipedia.org/wiki/Radix_sort
It took a bit of time to pick though your countSort routine and attempt to determine just what it was you were doing compared to a normal radix sort. There are some versions that split the iteration and the actual sort routine which appears to be what you attempted using both countSort and sort functions. However, after going though that exercise, it was clear you had just missed including necessary parts of the sort routine. After fixing various compile/declaration issues in your original code, the following adds the pieces you overlooked.
In your countSort function, the size of your count array was wrong. It must be the size of the base, in this case 10. (you had 5) You confused the use of exp and base throughout the function. The exp variable steps through the powers of 10 allowing you to get the value and position of each element in the array when combined with a modulo base operation. You had modulo n instead. This problem also permeated you loop ranges, where you had a number of your loop indexes iterating over 0 < n where the correct range was 0 < base.
You missed finding the maximum value in the original array which is then used to limit the number of passes through the array to perform the sort. In fact all of your existing loops in countSort must fall within the outer-loop iterating while (m / exp > 0). Lastly, you omitted a increment of exp within the outer-loop necessary to applying the sort to each element within the array. I guess you just got confused, but I commend your effort in attempting to rewrite the sort routine and not just copy/pasting from somewhere else. (you may have copied/pasted, but if that's the case, you have additional problems...)
With each of those issues addressed, the sort works. Look though the changes and understand what it is doing. The radix sort/count sort are distribution sorts relying on where numbers occur and manipulating indexes rather than comparing values against one another which makes this type of sort awkward to understand at first. Let me know if you have any questions. I made attempts to preserve your naming convention throughout the function, with the addition of a couple that were omitted and to prevent hardcoding 10 as the base.
#include <stdio.h>
void prnarray (int *a, int sz);
void countSort (int arr[], int n, int base)
{
int exp = 1;
int m = arr[0];
int output[n];
int count[base];
int i;
for (i = 1; i < n; i++) /* find the maximum value */
m = (arr[i] > m) ? arr[i] : m;
while (m / exp > 0)
{
for (i = 0; i < base; i++)
count[i] = 0; /* zero bucket array (count) */
for (i = 0; i < n; i++)
count[ (arr[i]/exp) % base ]++; /* count keys to go in each bucket */
for (i = 1; i < base; i++) /* indexes after end of each bucket */
count[i] += count[i - 1];
for (i = n - 1; i >= 0; i--) /* map bucket indexes to keys */
{
output[count[ (arr[i]/exp) % base] - 1] = arr[i];
count[(arr[i]/exp)%n]--;
}
for (i = 0; i < n; i++) /* fill array with sorted output */
arr[i] = output[i];
exp *= base; /* inc exp for next group of keys */
}
}
int main (void) {
int arr[] = { 10, 6, 8, 2, 3 };
int n = 5;
int base = 10;
printf ("\n The original array is:\n\n");
prnarray (arr, n);
countSort (arr, n, base);
printf ("\n The sorted array is\n\n");
prnarray (arr, n);
printf ("\n");
return 0;
}
void prnarray (int *a, int sz)
{
register int i;
printf (" [");
for (i = 0; i < sz; i++)
printf (" %d", a[i]);
printf (" ]\n");
}
output:
$ ./bin/sort_count
The original array is:
[ 10 6 8 2 3 ]
The sorted array is
[ 2 3 6 8 10 ]
Like the title say, how I calculate the sum of n number of the form: 1+(1/2!)+⋯(1/n!)? I already got the code for the harmonic series:
#include <stdio.h>
int main( void )
{
int v=0,i,ch;
double x=0.;
printf("Introduce un número paracalcular la suma: ");
while(scanf("%d",&v)==0 || v<=0)
{
printf("Favor de introducir numeros reales positivos: ");
while((ch=getchar())!='\n')
if(ch==EOF)
return 1;
}
for (i=v; i>=1; i--)
x+=1./i;
printf("EL valor de la serie es %f\n", x);
getch();
return 0;
}
The question here is.. I already got the sum as the fraction, but how make the variable "i" factorial?
Note: I´m programming in language C, with DEV -C++ 4.9.9.2
You got a slightly more accurate answer for the harmonic summing 1./i + 1./(i-1) ... 1./1. Suggest you stay with that order.
[edit] Rewrite: Thanks to #pablo197 for pointing out the error of my ways.
To calculate harmonic and 1+(1/2!)+…+(1/n!), continue summing the least significant terms together first as that helps to minimize precision loss. Starting with the least significant term 1/n as sum, sum of that and the n-1 term is : sum = (1 + sum)/(n-1) and so on. (See below)
double x = 0.0;
double one_over_factorial_series = 0.0;
for (i = v; i >= 1; i--) {
x += 1.0/i;
one_over_factorial_series = (one_over_factorial_series + 1)/i;
}
printf("harmonic:%le\n", x);
// 2.828968e+00
printf("one_over_factorial:%.10le\n", one_over_factorial_series);
// 1.7182815256e+00
Add 1.0 or 1/0! to one_over_factorial_series, the result about e = 2.7182818284...
[Edit] Detail showing how direct n! calculation is avoided.
1 + (1/2!) + … + (1/n!) =
1/n! + 1/((n-1)!) + 1/((n-2)!) + 1/((n-3)!) + ... + 1 =
(1/n + 1)/((n-1)!) + 1/((n-2)!) + 1/((n-3)!) + ... + 1 =
((1/n + 1)/(n-1) + 1)/((n-2)!) + 1/((n-3)!) + ... + 1 =
...
((((1/n + 1)/(n-1) + 1)/(n-2) + 1)/(n-3) + 1)/(n-4) + ... =
If you're just looking for computing the first n factorials, I would suggest just computing them recursively, e.g.
factorial[0] = 1;
for (i = 1; i < n; i++) factorial[i] = factorial[i-1] * i;
However, unless you store them as floating point numbers, the large factorials are going to overflow really quickly.
Calculating factorial in this case is bad thing to do because it can cause overflow for small values of N . Use following pseudo code to get it in O(N) without overflow.
double sum = 0.0;
double acc = 1;
double error = 0.0000001;
for(i=1;i<=n;i++) {
acc = acc/i;
if(acc<error)
break;
sum = sum + acc;
}
print(sum);
More acurrate way of doing it though i feel it is unnecessary in case of factorials : -
double sum = 0.0;
double acc = 1;
for(i=n;i>=1;i--) {
sum = (sum + 1)/i;
}
print(sum);
Note:- Because the above method is built in reverse it more accurate but unfortunately more time consuming because it is O(N) even for higher values whereas the gain in accuracy is negligible as factorial function grows very fast hence error keeps on decreasing quickly.
The number n! is equal to the product of n and the preceding factorial, that is, (n - 1)!.
If you calculate n! in an iteration, you are doing n products.
In the next step, say n+1, you repeat again these n products followed by the multiplication by n+1.
This means that you are repeating the same operations again and again.
It is a better strategy to hold the previous factorial that was calculated in the step n, and then, in the step n+1, just to multiply the n! by n+1. This reduces the number of products to 1 in each iteration.
Thus, you can calculate the series in the following way:
int max_n = 20; /* This value can come from another point of the program */
int n; /* Initial value of the index */
double factorial_n = 1; /* It has to be initialized to 1, since the factorial of 0 is 1 */
double sum = 0.0; /* It has to be initialized to 0, in order to calculate the series */
for (n = 0; n <= max_n; )
{
sum += 1.0/factorial_n;
n++;
factorial_n *= n;
}
printf("Series result: %.20f\n", sum);
There are some numerical issues with this approach, but this go beyond the scope of your question.
About overflow: It is necessary to be carefull about the overflow of factorials after several iterations. However, I will not write code to handle overflow.
EDIT
I think that you have not to follow the suggestions of those people that advice to use a factorial function. This approach is very unefficient, since a lot of products are done in every iteration.
IN comparisson with that approach, the mine is better.
However, if you have plans to calculate these series very often, then my approach is not efficient anymore. Then, the right technique is that pointed out in the Bli0042's answer, that is: to hold the factorials in an array, and then just use them every time you need, without need to calculate them again and again in the future.
The resulting program would be this:
#include <stdio.h>
#define MAX_N 100
double factorial[MAX_N+1];
void build_factorials(double *factorial, int max)
{
factorial[0] = 1.0;
for (int j = 0; j <= max; )
{
j++;
factorial[j] = factorial[j-1] * j;
}
}
double exp_series(int n)
{
int j;
double sum;
if (n > MAX_N) /* Error */
return 0.0;
sum = 0.0;
for (j = n; j >= 0; j--)
sum += 1.0/factorial[j];
return sum;
}
int main(void)
{
int n;
double sum;
build_factorials(factorial, MAX_N);
printf("Series (up to n == 11): %.20f\n", exp_series(11));
printf("Series (up to n == 17): %.20f\n", exp_series(17));
printf("Series (up to n == 9): %.20f\n", exp_series(9));
getchar();
}
The iteration is done in reverse order inside the function exp_series() in order to improve the numerical issues (that is, to amortiguate the loss of precision when summing small terms).
The last code has side effects, because an external array is invoked inside the function exp_series().
However, I think that handling this would become my explanation more obscure.
Just, take it in account.