Can you give me advice about precision of computing Taylor series for an exponent? We have a degree of exponent and a figure of precision calculating as imput data. We should recieve a calculating number with a given precision as output data. I wrote a program, but when I calculate an answer and compare it with embedded function's answer, it has differents. Can you advice me, how I can destroy a difference between answeres? formula of exponent's calculating
#include "stdafx.h"
#include "iostream"
#include <math.h>
#include <Windows.h>
#include <stdlib.h>
using namespace std;
int Factorial(int n);
double Taylor(double x, int q);
int main()
{
double res = 0;
int q = 0;
double number = 0;
cout << "Enter positive number" << "\n";
cin >> number;
cout << "Enter rounding error (precision)" << "\n";
cin >> q;
cout << "\n" << "\n";
res = Taylor(number, q);
cout << "Answer by Taylor : " << res;
cout << "Answer by embedded function: " << exp(number);
Sleep(25000);
return 0;
}
int Factorial(int n) {
int res = 1;
int i = 2;
if (n == 1 || n == 0)
return 1;
else
{
while (i <= n)
{
res *= i;
i++;
}
return res;
}
}
double Taylor(double x, int q) {
double res = 1;
double res1 = 0;
int i =1;
while (i)
{
res += (pow(x, i) / Factorial(i));
if (int(res*pow(10, q)) < (res*pow(10, q)))
{//rounding res below
if ( ( int (res * pow(10,q+1)) - int(res*pow(10, q))) <5 )
res1 = (int(res*pow(10, q))) * pow(10, (-q));
else
res1 = (int(res*pow(10, q))) * pow(10, (-q)) + pow(10,-q);
return res1;
}
i++;
}
}
There are two problems in your code. First, the factorial is very prone to overflow. Actually I dont know when overflow occurs for int factorials, but I remember that eg on usual pocket calculators x! overflows already for x==70. You probably dont need that high factorials, but still it is better to avoid that problem right from the start. If you look at the correction that needs to be added in each step: x^i / i! (maths notation) then you notice that this value is actually much smaller than x^i or i! respectively. Also you can calculate the value easily from the previous one by simply multiplying it by x/i.
Second, I dont understand your calculations for the precision. Maybe it is correct, but to be honest for me it looks too complicated to even try to understand it ;).
Here is how you can get the correct value:
#include <iostream>
#include <cmath>
struct taylor_result {
int iterations;
double value;
taylor_result() : iterations(0),value(0) {}
};
taylor_result taylor(double x,double eps = 1e-8){
taylor_result res;
double accu = 1; // calculate only the correction
// but not its individual terms
while(accu > eps){
res.value += accu;
res.iterations++;
accu *= (x / (res.iterations));
}
return res;
}
int main() {
std::cout << taylor(3.0).value << "\n";
std::cout << exp(3.0) << "\n";
}
Note that I used a struct to return the result, as you should pay attention to the number of iterations needed.
PS: see here for a modified code that lets you use a already calculated result to continue the series for better precision. Imho a nice solution should also provide a way to set a limit for the number of iterations, but this I leave for you to implement ;)
Related
Find a sum of series by function s= 1!/y!+y!/3!+5!/y!......n
I don't know how to define fact function and is this code correct??
#include <math.h>
#include <iostream>
using namespace std;
float fact(float, float);
float sum(float, float);
int main() {
float n, x, s;
cout << "enter n and x" << endl;
cin >> n >> x;
s = sum(n, x);
cout << "sum =" << s << endl;
return 0;
}
float sum(float n, float x)
{
float x, s = 0;
for (int i = 0; i <= n; i++)
if (i % 2 == 0)
s = s + float(fact(i + 1) / fact(x));
else
s = s + float(fact(x) / fact(i + 1));
return s;
}
Whilst there are ways of defining the factorial of a floating-point number (using a gamma function), I doubt that is what you want. Similarly, the upper index n shouldn't be a float, either.
Your series as written looks awfully divergent.
As somebody else has said, it is rare to calculate new factorials from scratch: divisors of them tend to cancel, and whole terms of your series are simple multiples of earlier terms.
Here is the C++ program i wrote to solve the above series:
#include <iostream>
#include <cmath>
#include <cstdlib>
using namespace std;
int factorial(int a)
{
if (a > 1)
return a * factorial(a - 1);
else
return 1;
}
float series(float x, int n, float b)
{
if (abs(pow(x, n) / factorial(n)) < pow(10, -6) || abs(pow(x, n) / factorial(n)) == pow(10, -6)) { return b; }
else return b = (pow(x, n) / factorial(n)) + series(x, n + 1, b);
}
int main()
{
float x;
cout << "Enter x: "<<endl;
cin >> x;
cout << "E^x = " << series(x,0,0);
system("pause");
return 0;
}
It works fine when abs(x) < 2 but when abs(x) >= 2 this error appears:
Unhandled exception at 0x00F02539 in 33b.exe: 0xC00000FD: Stack
overflow (parameters: 0x00000001, 0x00F22FF8). occurred
I want to know why does this happen and how can i fix it?
Your problem is too deep recursion. Consider loop instead.
float series(float x)
{
const float epsilon = 1e-6f;
double error = 1;
double res = 1.f;
int iter = 1;
while (abs(error) > epsilon) {
error *= (x / iter++);
res += error;
cout << error << endl;
}
return res;
}
int main()
{
cout << "E^x = " << series(3);
system("pause");
return 0;
}
To be clearer about what happens:
When you call a function inside another function, the context of the parent function is saved to make room for the new context. When you make millions of inception, the memory stack in charge to save these context is full and overflows.
This is a Stack Overflow.
#include <iostream>
#include <cmath>
#include <cstdlib>
using namespace std;
int factorial[200];
int Factorial(int a)
{ if(a>0){
factorial[a]=a * factorial[a-1];
return factorial[a];
}
else
factorial[a]=1;
return 1;
}
double series(double x, int n, double b)
{ double temp=(abs(pow(x, n)) / Factorial(n));
if (temp <= 0.000001) { return b; }
else return (temp + series(x, n + 1, b));
}
int main()
{
float x;
cout << "Enter x: "<<endl;
cin >> x;
cout << "E^x = " << series(x,0,0);
system("pause");
return 0;
}
umm this solution is working. all i did was i took your code removed abs(pow(x, n) / factorial(n)) wherever its repeating and intialised to a new variable temp. then instead of < || == u can directly put <=. and rather than invoking a a function to calculate .000001 every time you could just give that value to reduce time further. however i believe that the reason why the code may not have worked is too much recursion. so for factorials i used dynamic programming to reduce its complexity. the above code is working perfectly fine.
I am to calculate the arithmetic mean, the geometric mean, and the harmonic mean for five numbers using a single while loop.
Here is what I have so far:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h>
float a;
float g;
float h;
sum1 = 0;
sum2 = 0;
sum3 = 0;
n = 5;
int k;
int main()
{
printf("Please Enter Five Integers:\n");
while (k = 0 && k < n && ++k);
{
scanf("%lf", &k);
sum1 = sum1 + k;
sum2 = sum2 * k;
sum3 = sum3 + (1.0 / k);
}
a = sum1 / n;
g = pow(sum2, 1 / n);
h = n / sum3;
printf("Arithmetic mean: %.3f\n", a);
printf("Geometric mean: %.3f\n", g);
printf("Harmonic mean: %.3f\n", h);
return 0;
Your C program has several issues.
You don't declare all the variables you are using, for example, and there's no need for them to be global.
Your initial value for sum2 (0) is wrong, it will never update because you repetedly multiply k times 0.
Then in pow(..., 1 / n) the 1/n is an integer division, so you are elevating to 0.
Your loop and its condition must be modified. Try this, I used double, instead of integers and float, but it depends on your assignment:
#include <stdio.h>
#include <math.h>
#define MAX 80
int main()
{
double a, g, h, k;
double sum = 0, prod = 1, sum_inv = 0;
const int n = 5;
int i = 0;
printf("Please, enter five numbers:\n");
char buffer[MAX];
while ( i < n ) {
fgets(buffer, MAX, stdin);
if ( sscanf(buffer, "%lf", &k) != 1 ) {
printf("Wrong format, floating point number expected\n");
continue;
}
if ( k == 0.0 ) {
printf("You should enter non zero numbers\n");
continue;
}
++i;
sum += k;
prod *= k;
sum_inv += (1.0 / k);
}
a = sum / n;
g = pow(prod, 1.0 / n);
h = n / sum_inv;
printf("Arithmetic mean: %.3f\n", a);
printf("Geometric mean: %.3f\n", g);
printf("Harmonic mean: %.3f\n", h);
return 0;
}
Apologies if this is brutal, but simply saying there are multiple issues and proceeding to correct them without explaining why they are issues or what was done to correct them doesn't make for a very good answer. It makes for homework cut-and-paste.
#define _CRT_SECURE_NO_WARNINGS
This is actually a bad idea. Those security warnings often tell you you're taking unnecessary risks. They are annoying, but often they are right.
#include <stdio.h>
#include <math.h>
These should be <cstdio> and <cmath>. Better still, don't use cstdio. Use the C++ equivalents.
float a;
float g;
float h;
sum1 = 0;
sum2 = 0;
sum3 = 0;
n = 5;
The preceding 4 variables do not have data types. All variables must have a type.
Further initializing sum2 to zero when it will be used to gather a product is a bad idea. 0 will result.
int k;
None of these variables need to be global and all of the variable names are non-descriptive. In a program this size, that's not horrible, but in a large program with dozens or thousands of variables, being able to read from the variable name what it does and what it contains is worth it's weight in gold.
int main()
{
printf("Please Enter Five Integers:\n");
while (k = 0 && k < n && ++k);
The ; is a bad mistake here. ; ends the instruction. It separates the loop from it's body, so you get a while the loops but does nothing else.
But let's look at the loop conditions shall we?
k = 0
this is the same as
k = 0
if (k)
Which is always false since k is 0. This exits the loop right here.
k < n
Which it always is because of k = 0. k is 0. A moot point because this never gets tested.
++k
is always true because at this point k will always be 1.
This screams read the textbook more closely because you missed quite a bit.
{
scanf("%lf", &k);
This line reads a floating point number into an integer. Not a good idea. The results will be bizarre at best.
In addition, the return code from scanf is untested so you have no way to tell whether or not scanf successfully read a value.
And this question is tagged C++. Why use C?
sum1 = sum1 + k;
sum2 = sum2 * k;
sum3 = sum3 + (1.0 / k);
That all looks good to me, other than being really bad, non-descriptive names.
}
a = sum1 / n;
Syntactically and logically sound.
g = pow(sum2, 1 / n);
1 / n will be performed entirely in integer arithmetic and certainly result in a fraction. Integers can't do fractions, so this will result in 0. Any number to the power of 0 is one.
h = n / sum3;
Looks good.
printf("Arithmetic mean: %.3f\n", a);
printf("Geometric mean: %.3f\n", g);
printf("Harmonic mean: %.3f\n", h);
Again, using C in C++. printf has it's uses, even in C++, and frankly this is one of those cases where I might use it (but with caution because there is a performance hit) because the C++ equivalent std::cout << "Arithmetic mean: " << std::fixed << std::setprecision(3) << a << '\n'; is brutally verbose.
return 0;
}
Revising this for C++
#include <cmath>
#include <iostream>
#include <iomanip>
#include <limits>
int main()
{
// discarded a, g, and h. Renamed the rest for easier reading
float sum = 0;
float product = 1;
float invSum = 0;
constexpr int MAX = 5;
int input;
std::cout <<"Please Enter Five Integers:" << std::endl;
int count = 0;
while (count < MAX)
{
if (std::cin >> input)
{ // read a good, or at least not horrible, number
// this will not handle the problem of "123abc" as input. "123" will be
// accepted and "abc" will be seen as a second token and rejected.
// proper handling of this is a question unto itself and has been asked
// hundreds of times.
sum += input;
product *= input;
invSum += (1.0 / input);
count++;
}
else
{ // clean up and ask for new input
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout <<"Bogus integer. Input again: " << std::endl;
}
}
std::cout << "Arithmetic mean: " << std::fixed << std::setprecision(3) << sum / MAX << '\n';
std::cout << "Geometric mean: " << std::fixed << std::setprecision(3) << pow(product, (1.0 / MAX)) << '\n';
std::cout << "Harmonic mean: " << std::fixed << std::setprecision(3) << MAX / invSum << '\n';
return 0;
}
I've written a few programs to find pi, this one being the most advanced. I used Machin's formula, pi/4 = 4(arc-tan(1/5)) - (arc-tan(1/239)).
The problem is that however many iterations I do, I get the same result, and I can't seem to understand why.
#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;
double arctan_series(int x, double y) // x is the # of iterations while y is the number
{
double pi = y;
double temp_Pi;
for (int i = 1, j = 3; i < x; i++, j += 2)
{
temp_Pi = pow(y, j) / j; //the actual value of the iteration
if (i % 2 != 0) // for every odd iteration that subtracts
{
pi -= temp_Pi;
}
else // for every even iteration that adds
{
pi += temp_Pi;
}
}
pi = pi * 4;
return pi;
}
double calculations(int x) // x is the # of iterations
{
double value_1, value_2, answer;
value_1 = arctan_series(x, 0.2);
value_2 = arctan_series(x, 1.0 / 239.0);
answer = (4 * value_1) - (value_2);
return answer;
}
int main()
{
double pi;
int iteration_num;
cout << "Enter the number of iterations: ";
cin >> iteration_num;
pi = calculations(iteration_num);
cout << "Pi has the value of: " << setprecision(100) << fixed << pi << endl;
return 0;
}
I have not been able to reproduce your issue, but here is a bit cleaned up code with a few C++11 idioms and better variable names.
#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;
// double arctan_series(int x, double y) // x is the # of iterations while y is the number
// then why not name the parameters accoringly? In math we usually use x for the parameter.
// prefer C++11 and the auto notation wherever possible
auto arctan_series(int iterations, double x) -> double
{
// note, that we don't need any temporaries here.
// note, that this loop will never run, when iterations = 1
// is that really what was intended?
for (int i = 1, j = 3; i < iterations; i++, j += 2)
{
// declare variables as late as possible and always initialize them
auto t = pow(x, j) / j;
// in such simple cases I prefer ?: over if-else. Your milage may vary
x += (i % 2 != 0) ? -t : t;
}
return x * 4;
}
// double calculations(int x) // x is the # of iterations
// then why not name the parameter accordingly
// BTW rename the function to what it is supposed to do
auto approximate_pi(int iterations) -> double
{
// we don't need all of these temporaries. Just write one expression.
return 4 * arctan_series(iterations, 0.2) - arctan_series(iterations, 1.0 / 239.0);
}
auto main(int, char**) -> int
{
cout << "Enter the number of iterations: ";
// in C++ you should declare variables as late as possible
// and always initialize them.
int iteration_num = 0;
cin >> iteration_num;
cout << "Pi has the value of: "
<< setprecision(100) << fixed
<< approximate_pi(iteration_num) << endl;
return 0;
}
When you remove my explanatory comments, you'll see, that the resulting code is a lot more concise, easier to read, and therefore easier to maintain.
I tried a bit:
Enter the number of iterations: 3
Pi has the value of: 3.1416210293250346197169164952356368303298950195312500000000000000000000000000000000000000000000000000
Enter the number of iterations: 2
Pi has the value of: 3.1405970293260603298790556436870247125625610351562500000000000000000000000000000000000000000000000000
Enter the number of iterations: 7
Pi has the value of: 3.1415926536235549981768144789384678006172180175781250000000000000000000000000000000000000000000000000
Enter the number of iterations: 42
Pi has the value of: 3.1415926535897940041763831686694175004959106445312500000000000000000000000000000000000000000000000000
As you see, I obviously get different results for different numbers of iterations.
That method converges very quickly. You'll get more accuracy if you start with the smallest numbers first. Since 5^23 > 2^53 (the number of bits in the mantissa of a double), probably the maximum number of iterations is 12 (13 won't make any difference). You'll get more accuracy starting with the smaller numbers. The changed lines have comments:
double arctan_series(int x, double y)
{
double pi = y;
double temp_Pi;
for (int i = 1, j = x*2-1; i < x; i++, j -= 2) // changed this line
{
temp_Pi = pow(y, j) / j;
if ((j & 2) != 0) // changed this line
{
pi -= temp_Pi;
}
else
{
pi += temp_Pi;
}
}
pi = pi * 4;
return pi;
}
For doubles, there is no point in setting precision > 18.
If you want an alternative formula that takes more iterations to converge, use pi/4 = arc-tan(1/2) + arc-tan(1/3), which will take about 24 iterations.
This is another way if some of you are interested. The loop calculates the integral of the function : sqrt(1-x²)
Which represents a semicircle of radius 1. Then we multiply by two the area. Finally we got the surface of the circle which is PI.
#include <iomanip>
#include <cmath>
#define f(x) sqrt(1-pow(x,2))
double integral(int a, int b, int p)
{
double d=pow(10, -p), s=0;
for (double x=a ; x+d<=b ; x+=d)
{
s+=f(x)+f(x+d);
}
s*=d/2.0;
return s;
}
int main()
{
cout << "PI=" << setprecision (9) << 2.0*integral(-1,1,6) << endl;
}
I am having the hardest time figuring out what is wrong here:
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
double fact(double);
double sinTaylor(double);
double cosTaylor(double);
int main()
{
double number, sineOfnumber, cosineOfnumber;
cout << "Enter a number, then I will calculate the sine and cosine of this number" << endl;
cin >> number;
sineOfnumber = sinTaylor(number);
cosineOfnumber = cosTaylor(number);
cout << fixed << endl;
cout << cosineOfnumber << endl;
cout << sineOfnumber << endl;
return 0;
}
double fact(double n)
{
double product = 1;
while(n > 1)
product *= n--;
return product;
}
double sinTaylor(double x)
{
double currentIteration, sumSine;
for(double n = 0; n < 5; n++)
{
currentIteration = pow(-1, n)*pow(x, 2*n+1) / fact(2*n+1);
sumSine += currentIteration;
}
return sumSine;
}
double cosTaylor(double y)
{
double currentIteration, sumCosine;
for(double n = 0; n < 5; n++)
{
double currentIteration = pow(-1, n)*pow(y, 2*n) / fact(2*n);
sumCosine += currentIteration;
}
return sumCosine;
}
Ok, so here's my code. I'm pretty content with it. Except for one thing:
sineOfnumber and cosOfnumber, after the calling of sinTaylor and cosTaylor, will add each other in the following cout line that will print each other.
In other words, if number is equal to lets say, .7853, 1.14 will be printed in the line that is intended to print cosineOfnumber, and sineOfnumber will print the result normally.
Can anyone help me identify why this is? Thank you so much!
Are you ever initializing the variables sumSine and sumCosine in your functions? They're not guaranteed to start at zero, so when you call += inside your loop you could be adding computed values to garbage.
Try initializing those two variables to zero and see what happens, as other than that the code seems okay.
The series for the sine is (sorry for the LaTeX):
sin(x) = \sum_{n \ge 0} \frac{x^{2 n + 1}}{(2 n + 1)!}
If you look, given term t_{2 n + 1} you can compute term t_{2 n + 3} as
t_{2 n + 3} = t_{2 n + 1} * \frac{x^2}{(2 n + 2)(2 n + 3)}
So, given a term you can compute the next one easily. If you look at the series for the cosine, it is similar. The resulting program is more efficient (no recomputing factorials) and might be more precise. When adding up floating point numbers, it is more precise to add them from smallest to largest, but I doubt that will make a difference here.