My code is supposed to calculate the 100th element of the sequence $x_0=1 ; x_i=\dfrac{x_{i-1}+1}{x_{i-1}+2}, i=1,2, \ldots$
I wrote iterative and recursive functions, but the results are not equal. Is it due to the lost of decimals?
Here is my driver code. The data from the file is i=100.
int main()
{
int i;
ifstream f ("data.txt");
f >> i;
double x_0= 1.00;
double x_100 = l(x_0, i);
ofstream g ("results.txt", ios::app);
g <<"\n100th element (by looping): " << x_100;
x_100 = r(x_0);
g <<"\n100th element (by recursion): " << x_100;
return 0;
}
l() is iterative function,
r() is recursive function
double l(double x, int i)
{
for (int j = 0; j<i ; j++){
x = (x + 1)/(x+2);
}
return x;
}
double r(double x)
{
if (x == 0)
return 1;
else
return (r(x-1) + 1) / (r(x-1) + 2);
}
Here are the results
100th element (by looping): 0.618034
100th element (by recursion): 0.666667
I the recursive function you do
(r(x-1) + 1) / (r(x-1) + 2)
With x == 1.0 that's equal to
(r(1-1) + 1) / (r(1-1) + 2)
That's of course equal to
(r(0) + 1) / (r(0) + 2)
And since r(0) will return 1 that equation is
(1.0 + 1) / (1.0 + 2)
There's no further recursion. The result is 2.0 / 3.0 which is 0.66667.
The iterative function l on the other hand will do 100 iterations where each iteration will change the value of x, making it even smaller and smaller.
The functions simply does different things, leading to different results.
Related
I'm working on a code that calculates PI with n terms. However, my code only works correctly with some values of n.
This piece of code even numbers do not work and when I switch up the negative sign the odd numbers do not work.
double PI(int n, double y=2){
double sum = 0;
if (n==0){
return 3;
}else if (n % 2 != 0){
sum = (4/(y*(y+1)*(y+2)))+(PI (n - 1 ,y+2)) ;
}else{
sum= -(4/(y*(y+1)*(y+2)))+PI (n - 1,y+2) ;
}
return sum;
}
int main(int argc, const char * argv[]) {
double n = PI (2,2);
cout << n << endl;
}
For n = 2 I expected a result of 3.1333 but I got a value of 2.86667
This is the formula for calculating PI , y is the denominator and n is the number of terms
Firstly, I will assume that a complete runnable case of your code looks like
#include <iostream>
using namespace std;
double PI(int n, double y=2){
double sum = 0;
if (n==0){
return 3;
}else if (n % 2 != 0){
sum = (4/(y*(y+1)*(y+2)))+(PI (n - 1 ,y+2)) ;
}else{
sum= -(4/(y*(y+1)*(y+2)))+PI (n - 1,y+2) ;
}
return sum;
}
int main(int argc, const char * argv[]) {
double n = PI (2,2);
cout << n << endl;
}
I believe that you are attempting to compute pi through the formula
(pi - 3)/4 = \sum_{k = 1}^{\infty} (-1)^{k+1} / ((2k(2k+1)(2k+2)),
(where here and elsewhere I use LaTeX code to represent mathy things). This is a good formula that converges pretty quickly despite being so simple. If you were to use the first two terms of the sum, you would find that
(pi - 3)/4 \approx 1/(2*3*4) - 1/(4*5*6) ==> pi \approx 3.13333,
which you seem to indicate in your question.
To see what's wrong, you might trace through your first function call with PI(2, 2). This produces three terms.
n=2: 2 % 2 == 0, so the first term is -4/(2*3*4) + PI(1, 4). This is the wrong sign.
n=1: 1 % 2 == 1, so the second term is 4/(4*5*6), which is also the wrong sign.
n=0: n == 0, so the third term is 3, which is the correct sign.
So you have computed
3 - 4/(2*3*4) + 4/(4*5*6)
and we can see that there are many sign errors.
The underlying reason is because you are determining the sign based on n, but if you examine the formula the sign depends on y. Or in particular, it depends on whether y/2 is odd or even (in your formulation, where you are apparently only going to provide even y values to your sum).
You should change y and n appropriately. Or you might recognize that there is no reason to decouple them, and use something like the following code. In this code, n represents the number of terms to use and we compute y accordingly.
#include <iostream>
using namespace std;
double updatedPI(int n)
{
int y = 2*n;
if (n == 0) { return 3; }
else if (n % 2 == 1)
{
return 4. / (y*(y + 1)*(y + 2)) + updatedPI(n-1);
}
else
{
return -4. / (y*(y + 1)*(y + 2)) + updatedPI(n-1);
}
}
int main() {
double n = updatedPI(3);
cout << n << endl;
}
The only problem with your code is that y is calculated incorrectly. It has to be equal to 2 * n. Simply modifying your code that way gives correct results:
Live demo: https://wandbox.org/permlink/3pZNYZYbtHm7k1ND
That is, get rid of the y function parameter and set int y = 2 * n; in your function.
I am calculating combination(15, 7) in C++.
I first used the following code and get the wrong answer due to a type promotion error.
#include <iostream>
int main()
{
int a = 15;
double ans = 1;
for(int i = 1; i <= 7; i++)
ans *= (a + 1 - i) / i;
std::cout << (int) ans;
return 0;
}
Output: 2520
So I changed ans *= (a + 1 - i) / i; to ans *= (double)(a + 1 - i) / i; and still get the wrong answer.
#include <iostream>
int main()
{
int a = 15;
double ans = 1;
for(int i = 1; i <= 7; i++)
ans *= (double) (a + 1 - i) / i;
std::cout << (int) ans;
return 0;
}
Output: 6434
Finally, I tried ans = ans * (a + 1 - i) / i, which gives the right answer.
#include <iostream>
int main()
{
int a = 15;
double ans = 1;
for(int i = 1; i <= 7; i++)
ans = ans * (a + 1 - i) / i;
std::cout << (int) ans;
return 0;
}
Output: 6435
Could someone tell me why the second one did not work?
If you print out ans without casting it to (int) you'll see the second result is 6434.9999999999990905052982270717620849609375. That's pretty darn close to the right answer of 6535, so it's clearly not a type promotion error any more.
No, this is classic floating point inaccuracy. When you write ans *= (double) (a + 1 - i) / i you are doing the equivalent of:
ans = ans * ((double) (a + 1 - i) / i);
Compare this to the third version:
ans = ans * (a + 1 - i) / i;
The former performs division first followed by multiplication. The latter operates left to right and so the multiplication precedes the division. This change in order of operations causes the results of the two to be slightly different. Floating point calculations are extremely sensitive to order of operations.
Quick fix: Don't truncate the result; round it.
Better fix: Don't use floating point for integral arithmetic. Save the divisions until after all the multiplications are done. Use long, long long, or even a big number library.
First one did not work because you have integer division there.
Difference btw second one and third one is this:
ans = ans * (double(a + 1 - i) / i); // second is equal to this
vs:
ans = (ans * (a + 1 - i)) / i; // third is equal to this
so difference is in order of multiplication and division. If you round double to integer instead of simply dropping fractional part you will get the same result.
std::cout << int( ans + 0.5 ) << std::endl;
I was given a task to write a program that displays:
I coded this:
#include<iostream.h>
#include<conio.h>
void main()
{
clrscr();
int a, n = 1, f = 1;
float s = 0;
cin >> a;
while(n <= a)
{
f = f * n;
s += 1 / (float)f;
n = n + 1;
}
cout << s;
getch();
}
So this displays -
s = 1 + 1/2! + 1/3! + 1/4! .... + 1/a!, including odd and even factorials.
For the past two hours I am trying to figure out how can I modify this code so that it displays the desired result. But I couldn't figure it out yet.
Question:
What changes should I make to my code?
You need to accumulate the sum while checking the counter n and only calculate the even factorials:
int n;
double sum = 1;
cin >> n;
for(int i = 2; i < n; ++i{
if(i % 2 == 0) sum += 1 / factorial(i);
}
In your code:
while(n <= a)
{
f = f * n;
// checks if n is even;
// n even if the remainder of the division by 2 is zero
if(n % 2 == 0){
s += 1 / (float)f;
}
n = n + 1;
}
12! is the largest value that fits in an 32 bit integer. You should use double for all the numbers. For even factorials, starting with f = 1 (0!), f = f * (n-1) * n, where n = 2, 4, 6, 8, ... .
You have almost everything you need in place (assuming you don't want to make design changes based on the issues brought up in the comments).
All you need to change is what you multiply f by in each step. To build up n! you are multiplying by n in each step. To build up (2n)! you would multiply by 2*n*(2*n-1)
Edit: Your second theory about what the instructor wants would need only slightly more of a change. Your inner loop could be replaced by
while(n < a)
{
f = f * n * (n+1);
s += 1 / f;
n = n + 2;
}
Edit2: To run your program I made several changes for I/O things you did that don't work in my copy of GCC. Hopefully those won't distract from the main point of the following code. I also added a second, more complicated and more accurate method of computing the answer to see how much was lost in floating point rounding.
So this code computes the answer twice, once by the method I suggested you change your code to and once by a more accurate method (using double instead of float and adding the numbers in the more accurate sequence via a recursive function). Then it display your answer and the difference between the two answers.
Running that shows the version I suggested gets all the displayed digits correct and is only wrong for the values of a I tried by tiny amounts that would need more display precision to notice:
#include<iostream>
using namespace std;
double fac_sum(int n, int a, double f)
{
if ( n > a )
return 0;
f *= n * (n-1);
return fac_sum(n+2, a, f) + 1 / f;
}
int main()
{
int a, n = 1;
float f = 1;
float s = 0;
cin >> a;
while(n < a)
{
f = f * n * (n+1);
s += 1 / f;
n = n + 2;
}
cout << s;
cout << " approx error was " << fac_sum( 2, a, 1.0)-s;
return 0;
}
For 8 that displays 0.54308 approx error was -3.23568e-08
I hope you understand the e-08 notation meaning the error is in the 8'th digit to the right of the .
Edit3: I changed f to float in this post because I had copied/tested thinking f was float, so parts of my answer didn't make sense when f was int
So I can calculate a sum of sequence without accuracy E.
int t=1, x, k;
float sum, a, result, factorial=1, E=0.0001;
for(k=0;k<=(n);k++){
while(t<=n){
factorial*=t;
t++;
}
sum=(pow(-x,k))/factorial;
sum+=sum;
//while(fabs(sum-???)<E){
// result=sum;
//}
}
So I know sum of sequence sum(k). But to calculate with accurace E, I must know sum of previous elements sum(k-1). How to get sum(k-1) from for loop?
Sorry for english.
is this a taylor series for e ^ (-x) ? if so you've written it out wrong. i don't think what you've got will converge.
http://www.efunda.com/math/taylor_series/exponential.cfm
e ^ (-x) is 1 + (-x) + (-x)^2/2! + (-x)^3/3! + ...
double calculate_power_of_e(double xx, double accuracy) {
double sum(1.0);
double term(1.0);
for (long kk=1; true; ++kk) {
term *= (-xx) / kk;
sum += term;
if (fabs(term) < accuracy)
break;
}
return sum;
}
printf("e^(-x)" = %.4f\n", calculate_power_of_e(5.0, .0001));
First a remark about the power formula that you apply: according to wikipedia you should add the terms pow(-x,k)/(k!) and not pow(-x,k)/(n!).
This leads to a small optimisation of your code: as k! = k * (k-1)! we can avoid the inner while loop and a lot of useless multiplications.
By the way, there is also an error in the way you build the sum: you always erase the previous result, and then add a second time the current term.
Once this is corrected, you just have to take care of an additional variable:
double myexpo(double x, int n=100) {
int k;
double sum = 1.0, pvsum, factorial = 1.0, E = 0.0001;
for (k = 1; k <= (n); k++){ // start with 1
pvsum = sum;
factorial *= k; // don't calculate factorial for 0.
sum += (pow(-x, k)) / factorial;
if (k > 1 && fabs(sum - pvsum) < E) { // check if diff is small enough
cout << k << " iterations" << endl;
break; // interupt the for loop if it's precise enough
}
}
return sum; // at the end of the loop sum is the best approximation
}
You can test this function with this:
double x;
do {
cout << "Enter number: ";
cin >> x;
cout << myexpo(x) << endl;
cout << exp(-x) << endl;
} while (x > 0);
Remark: I'd suggest to either use double or to use the f suffix for the float litterals (e.g. 0.001f), even if it works as is.
Check when the absolute value of the term becomes smaller than your desired accuracy.
double sum = 0, x = 1, k = 0, E = 0.0001, fact = 1;
while(true){
double term = pow(-x, k) / fact;
if(fabs(term) < E)
break;
sum += term;
fact *= (++k);
}
printf("e^(-x) = %.4f", sum);
When the term is insignificant compare to 1.0, stop looping.
By using recursion, and |x| is not too big, the smallest terms are summed first.
e(x) = 1 + x/1! + x*x/2! + x*x*x/3! + ...
double my_exp_term(double x, double term, unsigned n) {
if (term + 1.0 == 1.0) return term;
n++;
return term + my_exp_term(x, term*x/n, n);
}
double my_exp(double x) {
return 1.0 + my_exp_term(x, x, 1);
}
double y = my_exp(-1);
Exponential function
I'm writing a sine function that has to be recursive. I have written a sine function but am not really sure how to do it recursively. Could someone explain how to get started on this?
This is what I have so far:
/*--------------------------------------------------------------
Name: sine( double X );
Return: Function "sine" will return the
sine of X, where X is measured in radians.
--------------------------------------------------------------*/
double sine(double X)
{
double result = 0;
double term;
int k;
double lim;
k = 0;
lim = power(10, -8);
term = power(-1, k)*power(X, ((2*k) + 1)) / (factorial((2*k)+1));
result = term;
while (absolute(term) > lim)
{
k += 1;
term = power(-1, k)*power(X, ((2*k) + 1)) / (factorial((2*k)+1));
result += term;
}
return result;
}
EDIT: I used a wrapper function to solve this. Basically created another function called
double sine_rec(double X, double k)
and changed around the current code to fit in with that.
The way I would approach this would be to have another function sine(double X, int n) which takes another integer parameter - the number of terms to include in the power series approximation. Then this function could return something like [nth term in series] + sine(X, n - 1) (just remember a prior if statement to deal with n = 1).
You can eliminate the while loop by recursion in following way:
double sine(double X, int k = 0)
{
double result = 0;
double term;
double lim;
lim = power(10, -8);
term = power(-1, k)*power(X, ((2*k) + 1)) / (factorial((2*k)+1));
if (absolute(term) > lim)
{
return sine(X, k+1) + term;
}
else
{
return term;
}
}
But I cannot recommend doing this at all. (There are better solutions even to this recursion, but find them on your own)