This question already has answers here:
Calculate sum of 1+(1/2!)+…+(1/n!) n number in C language
(4 answers)
Closed 9 years ago.
Like the title says, how can I calculate the sum of n numbers 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 can I calculate the variable "i" factorial?
Note: I´m programming in language C, with DEV -C++ 4.9.9.2
For $n$ bigger than around $20,$ just use the mathematical constant $e.$ Below $20,$ it really doesn't matter what you do.
Usually by means of a recursive method, one can create a factorial function. Note that:
$$
n! = \left\{
\begin{array}{lr}
1 & : n = 1\\
n(n-1)! & : n > 1
\end{array}
\right.
$$
I guess this would mean something like
public int Factorial(int n)
{
return (n == 1 ? 1 : n * Factorial(n - 1));
}
ac = 1;
for (i=n; i>0; i--) ac = ac/i+1;
saves the computation of factorials and avoids rounding errors.
No recursion and no factorials.
double fraction=1, sum=0;
long i,n;
for(i=1;i<=n;i++)
sum+=(fraction/=i);
Output:
n=1
sum=1
n=2
sum=1.5
n=3
sum=1.666666666
n=1073741824
sum=1.71828182845904553488480814849026501178741455078125
Related
In some specific numbers my algorithm gets stuck. It never reaches the minimum approximation so we never get out of the while. I think I can either low my approximation requisites or use double for my numbers, but I'm trying to figure out other solutions.
I'm programming a babylonian algorithm to calculate roots. First I'm doing this in C and later I will do this in Assembly(University homework). When I try to find the root of numbers like 99999 the program iterates to infinity. I have already tried two different stop conditions, one of them I did exactly like this tutorial from geeks4geeks(the first one inside the site).
https://www.geeksforgeeks.org/square-root-of-a-perfect-square/
The second stop condition I tested was this:
while ((x*x - n) > e) {}
I tried something like this because it is more "relatable" to the method enunciation. The full code is showed below:
#include <stdio.h>
#include <math.h>
/*Returns the square root of n. Note that the function */
float squareRoot(float n)
{
/*We are using n itself as initial approximation
This can definitely be improved */
float x = n;
float y = 1;
float e = 0.000001; /* e decides the accuracy level*/
while ((x*x - n) > e) {
x = (x + y) / 2;
y = n / x;
// if(prev_err == x-y){
// printf("A aproximação por ponto flutuante alcançou o máximo possível para o caso\n");
// return x;
// }
// prev_err = x-y;
}
return x;
}
/* Driver program to test above function*/
int main()
{
int n;
printf("Insira o número cuja raiz deseja calcular\n");
scanf("%d", &n);
printf("Square root of %d is %.8f\n", n, squareRoot(n));
return 0;
}
An absolute tolerance will never work. If n is large, x.x - n can remain large and the loop will never stop. If n is tiny, x.x - n can too quickly become small and the result will be quite inaccurate.
Your test has another big flaw: if x.x - n < e, the iterations will stop immediately if the LHS is negative, whatever its value.
The cure is to take the absolute value and a relative tolerance.
A better cure is to
adapt the starting approximation to the magnitude of n (such as the nearest power of 4),
use a fixed number of iterations (with a good starting approximation, 7 iterations are enough).
float only can take 4 Size (bytes),
so If you want to calculate the square root for number greater than 4 bytes
You need to replace all float to double
like this:
#include <stdio.h>
#include <math.h>
/*Returns the square root of n. Note that the function */
double squareRoot(double n)
{
/*We are using n itself as initial approximation
This can definitely be improved */
double x = n;
double y = 1;
double e = 0.000001; /* e decides the accuracy level*/
while ((x*x - n) > e) {
x = (x + y) / 2;
y = n / x;
// if(prev_err == x-y){
// printf("A aproximação por ponto flutuante alcançou o máximo possível para o caso\n");
// return x;
// }
// prev_err = x-y;
}
return x;
}
/* Driver program to test above function*/
int main()
{
int n;
printf("Insira o número cuja raiz deseja calcular\n");
scanf("%d", &n);
printf("Square root of %d is %.8f\n", n, squareRoot(n));
return 0;
}
if u want learn more about Primitive Data Types size in c:
Primitive Data Types sizes
https://www.programiz.com/c-programming/c-data-types#:~:text=The%20size%20of%20float%20(single,data%20type)%20is%208%20bytes.
I was assigned a Hw that required me to calculate the value of e via using the series:
1 + 1/1! + 1/2! + ...1/n!
The value of e must be calculated until the value of n (entered by the user) is reached. Also, the value of 1/n! must be calculated until it's value is smaller than epsilon (also entered by the user).
I wrote the code, but there are some errors that compiler is telling me errors such as relational comparisons, use of ';' etc. Could anyone please help me fix the error. Thank you in advance.
Below is my code:
#include<stdio.h>
int factorial (int i)
{
if (i==0)
return 1;
else
return i*factorial(i-1);
}
int main(void) {
int i,n;
float e,ep;
printf("what is the value of epsilon: ");
scanf("%f",&ep);
printf("what is the value of n: ");
scanf("%d",&n);
for (i=1; i<=n, i++)
e= 1+1/factorial(i);
for(1/fatorial(i)<=ep)
printf("The value of e for the entered value of epsilon and n:%f",e);
return 0;
}
For more precision I would use double instead of float.
for (i=1; i<=n, i++)
e= 1+1/factorial(i);
This is wrong, you are not adding to e, you are assigning always the last
value of the series, which is always 0 (except for i = 1). So your e will
always be 1.
factorial is a function that returns an int. A int divided by an int is
an int and in C anything 1/x (for x > 1, x integer) is 0. You you to use
1.0 or cast at least one of the arguments to double (or float if you are
using floats):
double e = 1; // initializing e
for(i = 1; i <= n; ++i)
e += 1.0/factorial(i);
Also, the value of 1/n! must be calculated until it's value is smaller than epsilon, also entered by the user.
I don't understand what that means, if n is a fixed value given by the user,
what do you keep calculating? Is this really what the exercise says?
My interpretation would be: if by n steps |e_real - e_calculated| > epsilon,
keep incrementing n, otherwise stop. That would be
#include <stdio.h>
#include <math.h>
#include <stdint.h>
uint64_t factorial (uint64_t i)
{
if (i==0)
return 1;
else
return i*factorial(i-1);
}
int main(void)
{
int n;
double e = 1;
double epsilon;
printf("what is the value of epsilon: ");
scanf("%lf", &epsilon);
printf("what is the value of n: ");
scanf("%d",&n);
int i = 1;
while(1)
{
e += 1.0/factorial(i++);
if(i >= n && (fabs(e - M_E) < epsilon))
break;
}
printf("e: %.20lf, calculated e: %.20lf, error: %.20lf, steps: %d\n", M_E, e, fabs(e-M_E), i);
return 0;
}
Note: if you are using GCC, you have to compile it with the -lm option:
$ gcc e.c -oe -lm
You're not summing the series but actually set e to 1.
Because you set it to e + 1/factorial(n) but your factorial() returns an int which is very likely to be above 1, so the division is integral, and 1 divided by any greater number will give 0.
The last loop is very strange. Did you mean while rather than for? Note that factorial is mistyped. Moreover, no work is done in the loop's body other than printing the same message over and over.
When I try to calculate a 3-order determinant of a matrix ,I received bad outputs. At the 2-order one ,it work fine. To be more specific, I don't receive 9 values (v[1,1],v[1,2] etc) ,but instead i receive more than that. I thought is a problem to arrays ,but idk..
Code:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
void main(void) {
int i,j,n,i_max,j_max,ordin,i_m,j_m;
long int det;
int v[3][3];
int e[3];
int nr=0;
printf("\nIntroduceti ordinul matricei:\t");
scanf("%d",&n);
if (n==2) {
i_max=n;
j_max=n;
printf("\nIntroduceti valorile matricei:\n");
for (i=1;i<=i_max;i++) {
for (j=1;j<=j_max;j++) {
printf("v[%d,%d]= ",i,j);
scanf("%d",&(v[i][j]));
nr++;
e[nr] = v[i][j];
}
}
det = (e[1]*e[4])-(e[2]*e[3]);
printf("\nDeterminantul matricei este: %ld\n",det);
if (det != 0)
printf("Matricea de ordinul %d este inversabila !",n);
else printf("Matricea de ordinul %d nu este inversabila!",n);
} else if (n==3) {
i_m=n;
j_m=n;
printf("\nIntroduceti valorile matricei:\n");
for (i=1; i<= i_m; i++) {
for (j=1; j<= j_m; j++) {
printf("v[%d,%d]= ",i,j);
scanf("%d",&(v[i][j]));
nr++;
e[nr] = v[i][j];
}
}
det = (e[1]*e[5]*e[9])+(e[2]*e[6]*e[7])+(e[3]*e[4]*e[8])-(e[3]*e[5]*e[7])-(e[2]*e[4]*e[9])-(e[1]*e[6]*e[8]);
printf("Determinantul matricei este: %ld\n",det);
if (det != 0)
printf("Matricea de ordinul %d este inversabila!",n);
else
printf("Matricea de ordinul %d nu este inversabila!",n);
} else
printf("Ordinul matricei este incorect!");
return 0;
}
First, you declare
int v[3][3];
int e[3];
There are not enough items for e as you use it for v which has 3 x 3 = 9 elements.
So it seems that it would be solved by changing the second statement to
int e[9];
but it is not the end of story.
In the for loops you loop nor from 0 (which is common in C language), but from 1, so you need 1 more indices for all arrays!
So declare
int v[4][4]; /* for using indices from 1 to 3 */
int e[10]; /* for using indices from 1 to 9 */
First you say int v[3][3]; and int e[3]; and then you reach for elements like v[3][3] and e[4]. You seem to forget that arrays/matrices use 0-based indices. In other words, if you declare int v[3][3]; the only elements you should refer to are v[0][0]...v[2][2]. When reading data into v the for loops should go from 0 to 2, not from 1 to 3. Also, you clearly get out of the bounds of e, since it has 3 elements, but you go as far as e[9].
Btw, you also do not need to transfer things from v to e. After reading into v you can simply refer to v[0][0] as v[0], to v[0][1] as v[1], to v[1][0] as v[3] and to v[2][2] as v[8].
Also, you make pretty much the same errors in the part referring to the second order determinant.
This question already has answers here:
Concurrent Prime Generator
(10 answers)
Closed 8 years ago.
For project euler Problem 10, we are supposed to add all primes but that is taking my computer years to do it. Need a more efficient algorithm!
Heres my present C code:
#include <stdio.h>
int main(void)
{
int i, j, flag, sum=0;
for(i=3; i< 2000000; i = i + 2)
{
flag=0;
for(j=3; j<=i/2; j = j + 2)
{
if(i%j==0)
{
flag=1;
break;
}
}
if(flag==0)
sum += i;
}
printf ("%i", sum + 2);
}
Here is a slight improvement to your procedure, while keeping the same algorithm for testing primality:
Set the sum variable to the sum of the first two primes (i.e., 2+3 = 5)
Start from 5, and test only numbers that are adjacent to multiples of 6
For each number, test it only with divisors that are adjacent to multiples of 6
For each number, test it only with divisors between 5 and the square root of the number
Please note that this implementation improves the performance of the algorithm but not the time-complexity of the algorithm, and that there are more efficient methods for testing primality.
int i, j, iplus, jplus, flag, iroot, sum = 2+3;
int iroot = (int)ceil(sqrt((float)5));
int square = iroot*iroot;
for (i=5, iplus=2; i<2000000; i+=iplus, iplus=4-iplus)
{
flag = 0;
if (square < i)
{
iroot++;
square = iroot*iroot;
// instead of calculating the square root of the number every time,
// calculate it at the beginning, and increment it only when needed
}
for (j=5, jplus=2; j<=iroot; j+=jplus, jplus=4-jplus)
{
if (i%j == 0)
{
flag = 1;
break;
}
}
if (flag == 0)
sum += i;
}
printf("%i", sum);
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.