power series tayllor arrest criteria problem - c++

Hi guys i created a c program to confront taylor taylor series of cosine and interpolation but i have a problem . The problem is about the function cosine (calculated by using taylor method) because the programme always gives me a degree of 3 , or 1 . My teacher said that i should use this arrest criteria
x^(2k)/(2k!)<t where t is tau in my code , the tolerance. Really thanks to anyone who can help me!
#include<stdio.h>
#include<math.h>
double read_tolerance();
double put_x();
void cosine(double,double,int &,double,double);
double Li(int,int,double[],double);
double Pn(int,double[],double[],double);
void interpo_Lagrange(int);
int main()
{
int k=1;
double cos_initial=1,a=1;
double tau=read_tolerance();
double x=put_x();
cosine (cos_initial,a,k,x,tau);
interpo_Lagrange(k+1);
return 0;
}
double read_tolerance()
{
double t;
printf("\n choose the value of tolerance: ");
scanf("%lf", &t);
return t;
}
double put_x()
{
double x;
printf("\nput value of x: ");
scanf("%lf",&x);
return x;
}
void cosine(double coseno,double a,int &k,double x,double tau)
{
do {
a *= pow(-1,k)*((x*x) / (2*k));
coseno += a;
k=k+2;
}while (a> tau);
printf("value of cosine of %lf is %lf\n",x,coseno);
printf("degree with taylor is ' %d\n",k);
return ;
}
double Li(int i, int n, double x[], double X){
int j;
double prod=1;
for(j=0;j<=n;j++){
if(j!=i)
prod=prod*(X-x[j])/(x[i]-x[j]);
}
return prod;
}
double Pn(int n, double x[], double y[], double X){
double sum=0;
int i;
for(i=0;i<=n;i++){
sum=sum+Li(i,n,x,X)*y[i];
}
return sum;
}
void interpo_Lagrange(int n)
{
int i;
printf("the number of data-points are %d:\n",n);
double x[n];
double y[n];
printf("Enter the x data-points:\n");
for(i=1;i<=n;i++){
x[i]=Pi*i/(8);
printf("%lf\n",x[i]);
}
printf("Enter the y data-points:\n");
for(i=1;i<=n;i++){
y[i]=cos(Pi*i/(8));
printf("%lf\n",y[i]);
}
double X;
printf("Enter the value of x for which you want the interpolated value of y(x):\n");
scanf("%lf",&X);
printf("The interpolated value is %lf",Pn(n,x,y,X));
}

The implementation of tayllor series is incorrect and here is the right one
do {
a *= -((x * x) / ((2 * k - 1) * (2 * k)));
coseno += a;
k = k + 1;
} while (fabs(a) > tau);
i hope this fixes your problem

The first issue is that the term can be negative. So the stopping criteria
must used the absolute value of it.
Another issue is that the used formula is not correct. The calculation of the denominator (fatorial) was not correct.
A last issue is that is is better a little bit that the function return the calculated value: more clear.
Output:
cos calculated = 0.707107
Error = -1.14623e-010
#include <iostream>
#include <cmath>
double cosine (double x, double tolerance) {
double x2 = x*x;
double term = 1;
double y = 1;
int sign = -1;
int k = 2;
do {
term *= x2/(k*(k-1));
y += sign * term;
k += 2;
sign = -sign;
} while (term > tolerance);
return y;
}
int main() {
double tolerance = 1.0e-6;
double angle = 3.141592/4;
double calculated = cosine (angle, tolerance);
double exact = cos(angle);
double err = calculated - exact;
std::cout << "cos calculated = " << calculated << std::endl;
std::cout << "Error = " << err << std::endl;
return 0;
}

Related

I need to calculate the arctan(x) and the result is showing "nan", what is wrong with my code?

So the value that im getting is "nan" and i suspect something is wrong in my while statement.
#include <iostream>
#include <math.h>
using namespace std;
int main()
{ int n=1,c=0;
float x;
double sum=0, old_sum, diff=1000000,eps;
cin>>x>>eps;
while(abs(diff)>=eps){
old_sum=sum;
sum=sum+double(pow(x,n)/n)*double(pow(-1,c));
c++;
n+=2;
diff=sum-old_sum;
}
cout<<sum<<"\n";
cout<<atan(x);
return 0;
}
My input is 21 for x and 0.01 for eps and what i get is nan and the correct value done by the atan function.
There are several issues in your code:
You don't take into account that the formula is only valid for abs(x) <= 1. This can be solved by a little mathematical trick
You don't check that the formula converges effectively. This can be done with a test of the value of n
You are repetidly using the pow(.) function. This is useless. This doesn't provide bad results, but it is quite inefficient
#include <iostream>
#include <cmath>
int main() {
int n = 3;
int n_max = 200;
double x;
double eps;
std::cin >> x >> eps;
double x_sav = x;
x = x / (1.0 + sqrt(1+x*x)); // the trick to handle abs(x) > 1
int sign = -1;
double term = x;
double powerx = x;
double sum = x;
double x2 = x*x;
while (std::abs(term) > eps && n <= n_max) {
powerx *= x2;
term = powerx / n;
sum += term * sign;
n += 2;
sign = -sign;
}
if (n > n_max) {
std::cout << "The series did not converge\n";
return 1;
}
sum *= 2.0; // following of the trick
std::cout << sum << "\n";
std::cout << atan(x_sav) << "\n";
return 0;
}

Sum to infinity of geometric sequence

Question:
Write C++ function to evaluate the following formula for a given x:
The following code was designed in C++ on Visual Studio to be a solution of the above mentioned problem. However whenever I run the code what I am returned is the value of x; or the same value I input.
I don't understand what the problem may be, so I would appreciate any help given.
#include <iostream>
using namespace std;
unsigned long fact(int n) {
if (n <= 1) {
return 1;
}
else {
return n * fact(n - 1);
}
}
unsigned long f(int x, int n) {
static unsigned long term;
static unsigned long sum = 0;
do {
term = pow(x, (2 * n + 1)) / fact((2 * n) + 1);
n++;
sum += term;
} while (term < 0.000001);
return sum;
}
int main() {
int y = 0;
int x;
cout << "enter x" << endl;
cin >> x;
cout << f(x, y) << endl;
system("pause");
}
I suggest you don't calculate powers and factorials on each iteration. Each next term can be generated by multiplying the previous one by x^2 / [n(n+1)]:
double sinh_in_disguise(const double x) {
const double x_sq = x * x;
double term = x;
double sum = 0;
double n = 2;
while (true) {
const double new_sum = sum + term;
if (new_sum == sum)
break;
sum = new_sum;
term *= x_sq / (n * (n + 1));
n += 2;
}
return sum;
}
int main() {
std::cout.precision(16);
double x = 2.019;
std::cout << sinh_in_disguise(x) << std::endl; // prints 3.699001094869803
std::cout << std::sinh(x) << std::endl; // prints 3.699001094869803
}
put double datatype in the whole code and it will work perfectly

Recursive function outputs a wrong value

In this code the output is 'r' instead of 'r0'
Instead of doing the operations it outputs me the first 'r' (equals 100) and does not do the process.
I´m trying to program an operation like (x_0 = x + (nt²/(2(x+(n(t-1)²/2(x+(n(t-3)²/2(x + (n(t-4)²...)²)²)²)²)²)²)²)²) in where the process is repeated until the variable 't' is '0'(because each time the operation is done 't' get a '-1').
#include <iostream>
#include "math.h"
using namespace std;
int operation(float r,
float r0,
float recursiva,
float operacion,
float recursivaPrincipal2,
float recursivaPrincipal,
float p,
float n,
long long t,
float q,
float potenciaQ,
float c,
float potenciaC,
float t2,
float division);
float r = 100;
float t = 10000;
float r0;
float recursiva;
float operacion;
float recursivaPrincipal2;
float recursivaPrincipal;
float p;
float n;
float q;
float potenciaQ;
float c;
float potenciaC;
float t2;
float division;
int main() {
r0 = r + operacion;
potenciaQ = pow(10,10);
q = 6 * potenciaQ;
potenciaC = pow(10,2);
c = 5 * potenciaC;
while (t = 10000, t = t - 1, t > 0) {
t2 = t * t;
n = q * t2;
operacion = n / recursivaPrincipal;
recursivaPrincipal2 = recursiva * recursiva;
recursivaPrincipal = 2 * recursivaPrincipal2;
recursiva = r + operacion;
if (t == 0) {
system("pause");
return 0;
}
cout << "Solucion: " << r0 << endl;
}
}
i want to do something like this
I'm so sorry if this code offended you (comments look like it) but I'm not very good, this is my first c++ code (and last I think)
The answer is based on what i get from your question
Please do expand your mathematical expression for t=3 and append an image of it
by far what i got from your expression you need this
float func(int t,int n,int x)
{
if (t==1)
{
return (x + (n/2)*(n/2)) * (x + (n/2)*(n/2));
}
return x + (n*t*t)/(2*func(t-1,n,x)) ;
}
According to the picture you have uploaded this is my code
Don't use 0 for n
#include<iostream>
using namespace std;
double partSolver(int x,int p, int n)
{
if(n==0) return 2*x*x;
double val = x - ( (p*n*n) / partSolver(x,p,n-1) );
return 2*val*val ;
}
double solver(int x,int p,int n)
{
return (n*n * 2) / partSolver(x,p,n-1);
}
int main()
{
cout<<"The Solution is: "<<solver(3,2,1)<<endl;
return 0;
}

Sin algorithm not working

I made a c++ program that calculates sin without math.h. Im using this algorithm for my program https://ibb.co/bTnQnS. I enter 45 degrees, the program converts degrees to radians, the program uses the algorithm, and the program outputs -0.868597. The program should output 0.70710678 or √2/2. What am I doing wrong with the algorithm?
Code:
#include "stdafx.h"
#include <iostream>
using namespace std;
double sin(int input, int decimal_count);
int factorial(int n);
double deg_to_rad(int deg);
double power(double base, int power);
int main(){
double angle;
int decimal;
cout << sin(45,8) << endl;
//end
system("pause");
return 0;
}
double sin(int input, int accuracy) {
int odds = 3;
double sin;
double rads = deg_to_rad(input);
for (int i = 1; i <= accuracy; i += 1) {
if (i==1) {
sin = power(rads, odds) / factorial(odds);
}
else if (i%2==0) {
sin = (power(rads, odds) / factorial(odds)) + sin;
}
else {
sin = (power(rads, odds) / factorial(odds)) - sin;
}
odds = odds + 2;
}
sin = sin - rads;
return sin;
}
int factorial(int n) {
int fact = 1;
for (int j = 1; j <= n; j+=1) {
fact = fact * j;
}
return fact;
}
double deg_to_rad(int deg) {
return deg*(3.14159265/180);
}
double power(double base, int power) {
double ans = 1;
for (int k = 1; k <= power; k+=1) {
ans = ans * base;
}
return ans;
}
your taylor series expansion function is incorrect. :)
you have to disregard all even terms.
I have fixed it for you (i removed some windows specific stuff as I don;t have a windows machine: the stdfax.h header and the calls to pause were removed)
# include <cstdlib>
# include <iostream>
using namespace std;
double sin(int input, int decimal_count);
int factorial(int n);
double deg_to_rad(int deg);
double power(double base, int power);
int main(){
double angle;
int decimal;
cout << "The sine value is: " << sin(45,8) << endl;
//end
system("sleep 2");
return 0;
}
double sin(int input, int accuracy) {
int odds = 3;
double sin;
double rads = deg_to_rad(input);
bool negative_flag = true;
cout << "You entered " << input << " degrees" << endl;
cout << "This is " << rads << " radians" << endl;
sin = rads;
for (int taylor_term = 3; taylor_term <= 7; taylor_term += 2) {
double term = (double)(power(rads, taylor_term) / factorial(taylor_term));
if (negative_flag) {
term = -1 * term;
}
negative_flag = !(negative_flag);
sin += term;
}
return sin;
}
int factorial(int n) {
int fact = 1;
for (int j = 1; j <= n; j+=1) {
fact = fact * j;
}
return fact;
}
Running this output
You entered 45 degrees
This is 0.785398 radians
The sine value is: 0.707106
Explanation
The taylor series expansion for sine is a series of terms with odd taylor's coefficients that alternate in sign. In my code the alternating signs is effected by the flag. I've also taken into account only the first 3 terms of the taylor series expansion.
Other than that, the line double term = (double)(power(rads, taylor_term) / factorial(taylor_term)); calculates every term in the taylor series expansion.
negative_flag = !(negative_flag); resets the flag sign for the next term.
Addressing your comment and where your code was a bit wrong
Below is your sin func with minimal changes to make it work.
What you were doing wrong
These are just minimal edits, performing these edits would naturally be followed up with some code style cleanup. eg: the if and else block(not else if) have almost the exact same code
sin was not being initialized before being modified
the attribution to correct signs the taylor terms in the if blocks was not correct.
the extra subtraction of rads at the end from sin was not required. Once these things were fixed, your code works :)
int odds = 3;
double sin ;
double rads = deg_to_rad(input);
sin = rads;
for (int i = 1; i <= accuracy; i += 1) {
if (i==1) {
sin = sin - power(rads, odds) / factorial(odds);
}
else if (i%2==0) {
sin = (power(rads, odds) / factorial(odds)) + sin;
}
else {
sin = -(power(rads, odds) / factorial(odds)) + sin;
}
odds = odds + 2;
}
return sin;

Unknown error using the c++ eigen library

I am a graduate student at Florida State University studying financial mathematics. I am still a bit of a novice with C++ but I am trying to implement the Longstaff-Schwartz method for pricing of American options. Although, the algorithm in the journal is a bit daunting thus I am trying to convert the code that was written in Matlab and change it into C++. Essentially I am using the Matlab code as a guide.
I was referred by some stackexchange users to use the Eigen library which contains a good matrix class. Unfortunately the website here does not show me how to make my own function from the class. What I am stuck on is making a C++ function for the function in Matlab that does this:
Say t = 0:1/2:1 then in Matlab the output will be t = 0 0.500 1
So using the Eigen class I created a function called range to achieve the latter above. The function looks like this:
MatrixXd range(double min, double max, double N){
MatrixXd m(N,1);
double delta = (max-min)/N;
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++){
m(i,j) = min + i*delta;
}
}
return m;
}
I do not have any errors on my IDE (Ecclipse) but when I run my code and test this function I get this error message:
c:\mingw\include\c++\6.2.0\eigen\src/Core/PlainObjectBase.h:736:7:
error: static assertion failed:
FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED
I am not sure what is wrong. Any suggestions on achieving what I am trying to do or any suggestions at all are greatly appreciated.
Taking the suggestion by Martijn Courteaux, I changed $N$ into an int now but I now receive a new error that I do not understand:
c:\mingw\include\c++\6.2.0\eigen\src/Core/Matrix.h:350:7: error: static
assertion failed: THIS_METHOD_IS_ONLY_FOR_VECTORS_OF_A_SPECIFIC_SIZE
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 3)
For sake of completeness I will post my whole code below:
#include <iostream>
#include <cmath>
#include <limits>
#include <algorithm>
#include <Eigen/Dense>
#include <Eigen/Geometry>
using namespace Eigen;
using namespace std;
double LaguerreExplicit(int R, double x); // Generates the (weighted) laguerre value
double payoff_Call(double S, double K); // Pay off of a call option
double generateGaussianNoise(double mu, double sigma); // Generates Normally distributed random numbers
double LSM(int T, double r, double sigma, double K, double S0, int N, int M, int R);
// T Expiration time
// r Riskless interest rate
// sigma Volatility
// K Strike price
// S0 Initial asset price
// N Number of time steps
// M Number of paths
// R Number of basis functions
MatrixXd range(double min, double max, int N);
int main(){
MatrixXd range(0, 1, 2);
}
double payoff_Call(double S, double K){
double payoff;
if((S - K) > 0)
{
payoff = S - K;
}else
{
payoff = 0.0;
}
return payoff;
}
double LaguerreExplicit(int R, double x){
double value;
if(R==0)
{
value = 1;
}
else if(R==1)
{
value = 0.5*(pow(x,2) - 4.0*x + 2);
}
else if(R==3)
{
value = (1.0/6.0)*(-1*pow(x,3) + 9*pow(x,2) - 18*x + 6);
}
else if(R==4)
{
value = (1.0/24.0)*(pow(x,4) - 16*pow(x,3) + 72*pow(x,2) - 96*x + 24);
}
else if(R==5)
{
value = (1.0/120.0)*(-1*pow(x,5) + 25*pow(x,4) - 200*pow(x,3) + 600*pow(x,2) - 600*x + 120);
}
else if (R==6)
{
value = (1.0/720.0)*(pow(x,6) - 36*pow(x,5) + 450*pow(x,4) - 2400*pow(x,3) + 5400*pow(x,2) - 4320*x + 720);
}
else{
cout << "Error!, R is out of range" << endl;
value = 0;
}
value = exp(-0.5*x)*value; // Weighted used in Longstaff-Scwartz
return value;
}
double generateGaussianNoise(double mu, double sigma)
{
const double epsilon = std::numeric_limits<double>::min();
const double two_pi = 2.0*M_PI;
static double z0, z1;
static bool generate;
generate = !generate;
if (!generate)
return z1 * sigma + mu;
double u1, u2;
do
{
u1 = rand() * (1.0 / RAND_MAX);
u2 = rand() * (1.0 / RAND_MAX);
}
while ( u1 <= epsilon );
z0 = sqrt(-2.0 * log(u1)) * cos(two_pi * u2);
z1 = sqrt(-2.0 * log(u1)) * sin(two_pi * u2);
return z0 * sigma + mu;
}
MatrixXd range(double min, double max, int N){
MatrixXd m(N,1);
double delta = (max-min)/N;
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++){
m(i,j) = min + i*delta;
}
}
return m;
}
double LSM(int T, double r, double sigma, double K, double S0, int N, int M, int R){
double dt = T/N;
MatrixXd m(T,1);
return 0;
}
Here is the corrected function code that I fixed:
VectorXd range(double min, double max, int N){
VectorXd m(N + 1);
double delta = (max-min)/N;
for(int i = 0; i <= N; i++){
m(i) = min + i*delta;
}
return m;
}
Mistake is here:
MatrixXd range(double min, double max, double N){
MatrixXd m(N,1);
N is a double. The arguments of MatrixXd::MatrixXd(int, int) are int.
You presumably want to make N an int.
In regard to your edit:
Second mistake is here:
MatrixXd range(0, 1, 2);
in the main() function. Not sure what you are trying to do here, but that constructor is not valid. EDIT: Ah I believe I have an idea. You are trying to call your function named range. Do this like this:
MatrixXd result = range(0.0, 1.0, 2);