I recently started programming and I was doing some exercises when I bumped into one that said:
Write a program that can calculate an approximate value of the e constant with the formula e=1+1/1!+1/2!+1/3!+... using while and if if necessary. You cannot use do...while or for.
I wrote my code and I could almost swear the program needs two while loops, but, as you may be guessing, it doesn't work properly. Here's my code:
#include<stdio.h>
int main()
{
float number=3, factorial=1, constant=0, counter=3, variable=0;
float euler=0;
while(counter>1)
{
variable = number;
while(number>1)
{
factorial = factorial*number;
number--;
} // number is now 0, or that's what I think
constant = (1/factorial)+constant;
counter--;
variable = variable-1; // variable is still number?
number = variable; // to have a variable called number again?
}
euler = constant+1; // the 1 in the original formula...
printf("e = : %f\n", euler);
return 0;
}
It doesn't display the correct answer, hope you can help me. Thanks a lot!
Your iteration is too few times. Iterate more to get more accurate value.
You will have to initialize factorial in each loop to calculate factorial in this way.
You forgot to add 1/1!.
Try this:
#include<stdio.h>
int main(void)
{
float number=30, factorial=1, constant=0, counter=30, variable=0;
float euler=0;
while(counter>1)
{
variable=number;
factorial = 1;
while(number>1)
{
factorial=factorial*number;
number--;
}//number is now 1
constant=(1/factorial)+constant;
counter--;
variable=variable-1;
number=variable;
}
euler=constant+1+(1/1.f);//the 1 and 1/1! in the original formula...
printf("e = : %f\n", euler);
return 0;
}
As pointed by #MikeCAT, various coding errors.
As OP's iteration count was low: 3 resulting in low accuracy. As all the terms are eventually added to 1.0 (missed by OP), once a term plus 1.0 is still 1.0, it is about time to quit searching for smaller terms. Typically about 18 iterations with typical double.
When computing the sum of a series, a slightly more accurate answer is available by summing the smallest terms first, in this case, the last terms as done by OP. This can be done using a recursive summation to avoid lots of factorial recalculation.
double e_helper(unsigned n, double term) {
double next_term = term/n;
if (next_term + 1.0 == 1.0) return next_term;
return next_term + e_helper(n+1, next_term);
}
double e(void) {
return 1.0 + e_helper(1, 1.0);
}
#include <stdio.h>
#include <float.h>
#include <math.h>
int main(void) {
printf("%.*f\n", DBL_DECIMAL_DIG - 1, e());
printf("%.*f\n", DBL_DECIMAL_DIG - 1, exp(1));
puts("2.71828182845904523536028747135266249775724709369995...");
}
Output
2.7182818284590451
2.7182818284590451
2.71828182845904523536028747135266249775724709369995...
#include <stdio.h>
#include <math.h>
int main()
{
printf("e = : %.20lf\n", M_E );
return 0;
}
C math library have constant M_E as Euler's number. But, this may not be what you want.
Finding eulers constant 'e' with the formula e = 1 + 1/1! + 1 /2! ....
only using while loop
For beginners
#include <stdio.h>
int main (void) {
float n =5 , fact = 1 , f , x = 0 , e ,i ; //taking input or n as 5 ,our formula now is e = 1+ 1/1! + 1/2! + 1/3! + 1/4! + 1/5! ; as the formula depends upon the input value of n
while(n >=1 ) { /* We need to find factorial of n no of values, so keeping n in a loop starting with 5....1 , atm n is 5 */
f = n ; // let f = n , i.e, f = 5
fact = 1 ;
while(f >= 1 ){ //This while loops finds the factorial of current n value , ie. 5 ;
fact = fact * f ;
f -- ;
}
i = 1 / fact ; // i finds the 1/fact! of the formula
x = i + x ; // x = i + x ; where x = 0 ; , This eq adds all the 1/fact values , atm its adding 1/ 5 !
n-- ; // n decrements to 4 , and the loop repeats till n = 1 , and finally x has all the 1/factorial part of the eulers formula
}
//exiting all the loops since, we now have the values of all the 1/factorial,i.e x : part of the eulers formula
e = 1 + x ; // eulers e = 1 + x , where x represents all the addition of 1/factorial part of the eulers formula
printf ("e : %f",e ); //Finally printing e
return 0 ;
}
Output :
e : 2.716667
Related
I'm trying to find ex without using math.h. My code gives wrong anwsers when x is bigger or lower than ~±20. I tried to change all double types to long double types, but it gave some trash on input.
My code is:
#include <stdio.h>
double fabs1(double x) {
if(x >= 0){
return x;
} else {
return x*(-1);
}
}
double powerex(double x) {
double a = 1.0, e = a;
for (int n = 1; fabs1(a) > 0.001; ++n) {
a = a * x / n;
e += a;
}
return e;
}
int main(){
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
int n;
scanf("%d", &n);
for(int i = 0; i<n; i++) {
double number;
scanf("%lf", &number);
double e = powerex(number);
printf("%0.15g\n", e);
}
return 0;
}
Input:
8
0.0
1.0
-1.0
2.0
-2.0
100.0
-100.0
0.189376476361643
My output:
1
2.71825396825397
0.367857142857143
7.38899470899471
0.135379188712522
2.68811714181613e+043
-2.91375564689153e+025
1.20849374134639
Right output:
1
2.71828182845905
0.367879441171442
7.38905609893065
0.135335283236613
2.68811714181614e+43
3.72007597602084e-44
1.20849583696666
You can see that my answer for e−100 is absolutely incorrect. Why does my code output this? What can I do to improve this algorithm?
When x is negative, the sign of each term alternates. This means each successive sum switches widely in value rather than increasing more gradually when a positive power is used. This means that the loss in precision with successive terms has a large effect on the result.
To handle this, check the sign of x at the start. If it is negative, switch the sign of x to perform the calculation, then when you reach the end of the loop invert the result.
Also, you can reduce the number of iterations by using the following counterintuitive condtion:
e != e + a
On its face, it appears that this should always be true. However, the condition becomes false when the value of a is outside of the precision of the value of e, in which case adding a to e doesn't change the value of e.
double powerex(double x) {
double a = 1.0, e = a;
int invert = x<0;
x = fabs1(x);
for (int n = 1; e != e + a ; ++n) {
a = a * x / n;
e += a;
}
return invert ? 1/e : e;
}
We can optimize a bit more to remove one loop iteration by initializing e with 0 instead of a, and calculating the next term at the bottom of the loop instead of the top:
double powerex(double x) {
double a = 1.0, e = 0;
int invert = x<0;
x = fabs1(x);
for (int n = 1; e != e + a ; ++n) {
e += a;
a = a * x / n;
}
return invert ? 1/e : e;
}
For values of x above one or so, you may consider to handle the integer part separately and compute powers of e by squarings. (E.g. e^9 = ((e²)²)².e takes 4 multiplies)
Indeed, the general term of the Taylor development, x^n/n! only starts to decrease after n>x (you multiply each time by x/k), so the summation takes at least x terms. On another hand, e^n can be computed in at most 2lg(n) multiplies, which is more efficient and more accurate.
So I would advise
to take the fractional part of x and use Taylor,
when the integer part is positive, multiply by e raised to that power,
when the integer part is zero, you are done,
when the integer part is negative, divide by e raised to that power.
You can even spare more by considering quarters: in the worst case (x=1), Taylor requires 18 terms before the last one becomes negligible. If you consider subtracting from x the immediately inferior multiple of 1/4 (and compensate multiplying by precomputed powers of e), the number of terms drops to 12.
E.g. e^0.8 = e^(3/4+0.05) = 2.1170000166126747 . e^0.05
I'm learning C programming and made the algorithm below to solve this problem:
The code actually works, but initially the loop was with only 10 repetitions (rep <= 10), and the anwer for p = 3 was almost correct, so I changed rep <= 20. And It gave me just the exact answer from my calculator. And then I tried with a higher number, 12, and the output again was inaccurate. So I ended raising rep <= 35. If I get the loop for higher repetitions I get "-nan", and if the input for p is too high it will be the same. So just have to see the pattern to know that the problem of inaccuracy will get back as I input higher numbers which is not the case because the output will be NaN if I input a high value.
Is it possible to solve it without higher level functions? just want to know if my program is ok for the level in which I am now...
#include <stdio.h>
int main()
{
float p; //the power for e
float power; //the copy of p for the loop
float e = 1; //the e number I wanna raise to the power of p
int x = 1; //the starting number for each factorial generation
float factorial = 1;
int rep = 1; //the repeater for the loop
printf( "Enter the power you want to raise: " );
scanf( "%f", &p );
power = p;
while ( rep <= 35) {
while ( x > 1) {
factorial *= x;
x--;
}
e += p / factorial;
//printf("\nthe value of p: %f", p); (TESTER)
//printf("\nthe value of factorial: %f", factorial); (TESTER)
p *= power; //the new value for p
rep++;
factorial = 1;
x = rep; //the new value for the next factorial to be generated
//printf("\n%f", e); (TESTER)
}
printf("%.3f", e);
return 0;
}
Sorry if I had syntax/orthography errors, I'm still learning the language.
Before we begin, let's write your original code as a function, with some clean-ups:
float exp_original(float x, int rep = 35)
{
float sum = 1.0f;
float power = 1.0f;
for (int i = 1; i <= rep; i++)
{
float factorial = 1.0f;
for (int j = 2; j <= i; j++)
factorial *= j;
power *= x;
sum += power / factorial;
}
return sum;
}
There were some unnecessary variables you used which were removed, but otherwise the procedure is the same: compute the factorial from scratch.
Let's look at the ratio between successive terms in the series:
We can thus simply multiply the current term by this expression to get the next term:
float exp_iterative(float x, int rep = 35)
{
float sum = 1.0f;
float term = 1.0f;
for (int i = 1; i <= rep; i++)
{
term *= x / i;
sum += term;
}
return sum;
}
Seems much simpler, but is it better? Comparison against the C-library exp function (which we assume to be maximally precise):
x exp (C) exp_orig exp_iter
-------------------------------------------
1 2.7182817 2.718282 2.718282
2 7.3890562 7.3890567 7.3890567
3 20.085537 20.085539 20.085539
4 54.598148 54.598152 54.598152
5 148.41316 148.41318 148.41316
6 403.4288 403.42871 403.42877
7 1096.6332 1096.6334 1096.6334
8 2980.958 2980.9583 2980.9587
9 8103.084 8103.083 8103.083
10 22026.465 22026.467 22026.465
11 59874.141 59874.148 59874.152
12 162754.8 162754.77 162754.78
13 442413.41 -nan(ind) 442413.38
14 1202604.3 -nan(ind) 1202603.5
15 3269017.3 -nan(ind) 3269007.3
16 8886111 -nan(ind) 8886009
17 24154952 -nan(ind) 24153986
18 65659968 -nan(ind) 65652048
19 1.784823e+08 -nan(ind) 1.7842389e+08
20 4.8516518e+08 -nan(ind) 4.8477536e+08
The two custom implementations are neck-and-neck in-terms of precision, until x = 13 where the original gives NaN. This is because the highest power term 13^35 = 9.7278604e+38 exceeds the maximum value FLT_MAX = 3.40282e+38. The accumulated term in the iterative version never reaches anywhere near the limit.
i have the recurrence relation of
and the initials condition is
a0 = a1 = 0
with these two, i have to find the bit strings of length 7 contain two consecutive 0 which i already solve.
example:
a2 = a2-1 + a2-2 + 22-2
= a1 + a0 + 20
= 0 + 0 + 1
= 1
and so on until a7.
the problem is how to convert these into c?
im not really good at c but i try it like this.
#include<stdio.h>
#include <math.h>
int main()
{
int a[7];
int total = 0;
printf("the initial condition is a0 = a1 = 0\n\n");
// a[0] = 0;
// a[1] = 0;
for (int i=2; i<=7; i++)
{
if(a[0] && a[1])
a[i] = 0;
else
total = (a[i-1]) + (a[i-2]) + (2 * pow((i-2),i));
printf("a%d = a(%d-1) + a(%d-2) + 2(%d-2)\n",i,i,i,i);
printf("a%d = %d\n\n",i,total);
}
}
the output are not the same as i calculate pls help :(
int func (int n)
{
if (n==0 || n==1)
return 0;
if (n==2)
return 1;
return func(n-1) + func(n-2) + pow(2,(n-2));
}
#include<stdio.h>
#include <math.h>
int main()
{
return func(7);
}
First of uncomment the lines which initialized the 2 first elements. Then at the for loop the only 2 lines need are:
a[i]=a[i-1]+a[i-2]+pow(2, i-2);
And then print a i
In the pow() function, pow(x,y) = x^y (which operates on doubles and returns double). The C code in your example is thus doing 2.0*(((double)i-2.0)^(double)i)... A simpler approach to 2^(i-2) (in integer math) is to use the bitwise shift operation:
total = a[i-1] + a[i-2] + (1 << i-2);
(Note: For ANSI C operator precedence consult an internet search engine of your choice.)
If your intention is to make the function capable of supporting floating point, then the pow() function would be appropriate... but the types of the variables would need to change accordingly.
For integer math, you may wish to consider using a long or long long type so that you have less risk of running out of headroom in the type.
(C) calculate series
y = x - x3/3! + x5/5! - x7/7! + .....
where stopping criterion is
| xi/i! | <= 0.001
What I have tried :
#include<stdio.h>
#include<math.h>
int fact(int x){
if(x>1){
return x * fact(x-1);
}
else {
return 1 ;
}
}
int main () {
int x , i=1 , sign=1 ;
float result ;
scanf("%d",&x);
while(abs(pow(x,i)/fact(i))>0.001){
result += sign*(pow(x,i)/fact(i));
i+2;
sign = sign * -1 ;
}
printf("result= %f\n",result);
return 0 ;
}
the problem is
when i input 90 ... the output should be 1 ... ( it's like the sin(x) )
im getting a different output
The code (at least) misses to initialise result.
Change
float result;
to
float result = 0.f;
Also
i+2;
is a NOP (no-operation). It results in nothing. It adds 2 to i and does not assign the result to anything, "throughs away" the result.
To increment i by 2 do:
i = i + 2;
or
i += 2;
Also^2 using abs() won't work as it return int.
Use fabs() to get a floating point value.
Or just do not use it at all as it's argument will never be negative here.
As a final advice prefer using double over float, as floats accurary is limited.
The problem is very clear. You have to convert degree into radian before performing the loop. Your code has some other issues also.
Here is the rectified code, which gives you 1 for 90:
#include<stdio.h>
#include<math.h>
int fact(int x){
if(x>1){
return x * fact(x-1);
}
else {
return 1 ;
}
}
int main () {
int x , i=1 , sign=1;
double result, rad;
scanf("%d",&x);
rad = x/180.0*3.1415;
while((pow(x,i)/fact(i))>0.001){
result += sign*(pow(rad,i)/fact(i));
i+=2;
sign *= -1 ;
}
printf("result= %f\n",result);
return 0 ;
}
sin(90)=0.89399666360055789051826949840421...
Besides the unit confusion, your code is not very efficient, as you compute the powers and factorials from scratch on each term, when a nice recurrence exists.
Sin= x
Term= x
Factor= -x*x
i= 2
while |Term| > 0.001:
Term*= Factor / (i * (i+1))
Sin+= Term
i+= 2
Because of huge cancellation errors, this formula is not appropriate for large values of the argument. My own implementation gives -1.07524337969e+21 for 90.
If you compute it for 90-14*2*Pi instead, you get 0.893995..., not a so bad result.
An algorithm that calculates sin (x) using the following power series: sin (x) = (x / 1!) - (X ^ 3/3) + (x ^ 5/5!) - (! ^ x 7/7) + ... We stop the calculation when the difference between two succesive terms of the sum given is less than a certain tolerance.
I did this in c :
#include<stdio.h>
int main (void)
{
int n,i;
scanf("%d", &n);
for(i=2;i<=n;i=i+2)
{
if((i*i)%2==0 && (i*i)<= n)
printf("%d \n",(i*i));
}
return 0;
}
What would be a better/faster approach to tackle this problem?
Let me illustrate not only a fast solution, but also how to derive it. Start with a fast way of listing all squares and work from there (pseudocode):
max = n*n
i = 1
d = 3
while i < max:
print i
i += d
d += 2
So, starting from 4 and listing only even squares:
max = n*n
i = 4
d = 5
while i < max:
print i
i += d
d += 2
i += d
d += 2
Now we can shorten that mess on the end of the while loop:
max = n*n
i = 4
d = 5
while i < max:
print i
i += 2 + 2*d
d += 4
Note that we are constantly using 2*d, so it's better to just keep calculating that:
max = n*n
i = 4
d = 10
while i < max:
print i
i += 2 + d
d += 8
Now note that we are constantly adding 2 + d, so we can do better by incorporating this into d:
max = n*n
i = 4
d = 12
while i < max:
print i
i += d
d += 8
Blazing fast. It only takes two additions to calculate each square.
I like your solution. The only suggestions I would make would be:
Put the (i*i)<=n as the middle clause of your for loop, then it's checked earlier and you break out of the loop sooner.
You don't need to check and see if (i*i)%2==0, since 'i' is always positive and a positive squared is always positive.
With those two changes in mind you can get rid of the if statement in your for loop and just print.
Square of even is even. So, you really do not need to check it again. Following is the code, I would suggest:
for (i = 2; i*i <= n; i+=2)
printf ("%d\t", i*i);
The largest value for i in your loop should be the floor of the square root of n.
The reason is that the square of any i (integer) larger than this will be greater than n. So, if you make this change, you don't need to check that i*i <= n.
Also, as others have pointed out, there is no point in checking that i*i is even since the square of all even numbers is even.
And you are right in ignoring odd i since for any odd i, i*i is odd.
Your code with the aforementioned changes follows:
#include "stdio.h"
#include "math.h"
int main ()
{
int n,i;
scanf("%d", &n);
for( i = 2; i <= (int)floor(sqrt(n)); i = i+2 ) {
printf("%d \n",(i*i));
}
return 0;
}