Infinite loop calculating cubic root - c++

I'm trying to make a function that calculates the cubic root through Newton's method but I seem to have an infinite loop here for some reason?
#include <iostream>
#include <math.h>
using namespace std;
double CubicRoot(double x, double e);
int main()
{
cout << CubicRoot(5,0.00001);
}
double CubicRoot(double x, double e)
{
double y = x;
double Ynew;
do
{
Ynew = y-((y*y)-(x/y))/((2*y)+(x/(y*y)));
cout << Ynew;
} while (abs(Ynew-y)/y>=e);
return Ynew;
}

You have not updated your y variable while iteration.
Also using abs is quite dangerous as it could round to integer on some compilers.
EDIT
To clarify what I've mean: using abs with <math.h> could cause implicit type conversion problems with different compiles (see comment below). And truly c++ style would be using the <cmath> header as suggested in comments (thanks for that response).
The minimum changes to your code will be:
double CubicRoot(double x, double e)
{
double y = x;
double Ynew = x;
do
{
y = Ynew;
Ynew = y-((y*y)-(x/y))/((2*y)+(x/(y*y)));
cout << Ynew;
} while (fabs(Ynew-y)/y>=e);
return Ynew;
}

You can change
Ynew = y-((y*y)-(x/y))/((2*y)+(x/(y*y)));
to the equivalent, but more recognizable expression
Ynew = y*(y*y*y+2*x)/(2*y*y*y+x)
which is the Halley method for f(y)=y^3-x and has third order convergence.

Related

How to use the bisection method in boost C++ for a function with multiple arguments

I have below function in C++
#include <cmath>
#include <utility>
#include <iostream>
#include <boost/math/tools/roots.hpp>
double my_fn(double x, double y)
{
return x*x - y - 1;
};
int main() {
double min_x = 0.0; // min value of domain of x
double max_x = 10.0; // max value of domain of x
double y = 1;
// how to use boost's bisection to find solution of my_fn for y = 1
return (0);
}
As you see my_fn takes 2 arguments x and y. However I want to find solution of this function given y = 1.
Can you please help to find solution using bisection method?
#include <cmath>
#include <utility>
#include <iostream>
#include <boost/math/tools/roots.hpp>
double my_fn(double x, double y)
{
return x*x - y - 1;
};
int main() {
double min_x = 0.0; // min value of domain of x
double max_x = 10.0; // max value of domain of x
double y = 1;
auto x = boost::math::tools::bisect(
[y](double x){ return my_fn(x,y); },
min_x,
max_x,
[](double x,double y){return abs(x-y) < 0.01;}
);
std::cout << "The minimum is between x=" << x.first << " and x=" << x.second;
// how to use boost's bisection to find solution of my_fn for y = 1
return (0);
}
bisect is a template. The first parameter is a callable (the function to minimize), then the initial bracket (min and max) and the last parameter is a callable that evaluates the stop condition.
Alternatively you can write a function:
double my_fn_y1(double x) {
return my_fn(x,1);
}
and minimize that.
PS: The function does not return the solution, but rather the final interval which makes the stop condition true. The real solution is somewhere in that interval.
You can use a lambda (with good chance that the compiler inlines everything), like this:
#include <boost/math/tools/roots.hpp>
#include <iostream>
double my_fn(double x, double y) { return x * x - y - 1; };
int main()
{
double min_x = 0.0; // min value of domain of x
double max_x = 10.0; // max value of domain of x
double y = 1;
std::pair<double, double> result =
boost::math::tools::bisect([y](double x) { return my_fn(x, y); },
min_x,
max_x,
boost::math::tools::eps_tolerance<double>());
std::cout << "Result " << result.first << ", " << result.second;
return 0;
}
which prints:
Result 1.41421, 1.41421
You can read about lambda and lambda capture here: cpp.reference lambda section.

UPDATED Runge Kutta (RK4) 2nd order DE in C++ ERROR CODE

This is the updated version of Runge Kutta (RK4) 2nd order DE in C++ ERROR CODE
I am still experiencing difficulties with the code. Maybe this has to do with my limited knowledge of Runge-Kutta but when I run this code it doesn't produce an output.
#include <iostream>
#include <cmath>
//dvdt=-(g/L)*sin(theta)
//v=dxdt
double dxdt( double timepassed, double theta )
{
return theta/timepassed;
}
double L;
double g=9.8;
double coeff=-1*(g/L);
double dvdt( double timepassed, double x, double v)
{
return coeff*sin(x);
}
int main(){
// Standard Variables
double theta;
double theta1;
double h = 0.1;
double L;
double timepassed;
double time1;
// Input and Output Printing
std::cout << "Please input initial angle (in decimal radians), length of the pendulum (in meters) and the time desired (in seconds). Click ENTER key after each value."<<"\n";
std::cin >> theta1;
std::cin >> L;
std::cin >> timepassed;
// Specific Variable Declarations
double coeff=-1*(g/L);
double v = dxdt(theta1, timepassed);
double x = theta1;
double d2xdt2 = dvdt(timepassed, theta1, v);
// Defining K Values in Runge Kutta
double kx1,kv1;
double kx2, kv2;
double kx3, kv3;
double kx4, kv4;
double dt;
kx1=dt*dxdt(timepassed,x);
kv1=dt*dvdt(timepassed,x,v);
kx2=dt*dxdt(timepassed+dt/2,x+kx1/2);
kv2=dt*dvdt(timepassed+dt/2,x+kx1/2,v+kv1/2);
kx3=dt*dxdt(timepassed+dt/2,x+kx2/2);
kv3=dt*dvdt(timepassed+dt/2,x+kx2/2,v+kv2/2);
kx4=dt*dxdt(timepassed+dt,x+kx3);
kv4=dt*dvdt(timepassed+dt,x+kx3,v+kv3);
x = x + (1.0/6.0)*(kx1 + 2*kx2 + 2*kx3 + kx4);
v = v + (1.0/6.0)*(kx1 + 2*kv2 + 2*kv3 + kv4);
std::cout << "The angle is" << x; "\n";
std::cout << "The velocity is" << v;
}
Your system equations should be, as it is announced in the comment before it, as
//v=dx/dt
//dv/dt=d2x/dt2=-(g/L)*sin(x), where x=theta
double coeff;
double dxdt( double t, double x, double v) { return v; }
double dvdt( double t, double x, double v) { return coeff*sin(x); }
After the input of the parameters, the number coeff gets computed but not declared anew.
// Specific Variable Declarations
coeff = -(g/L);
Your step size appears to be 0.1. You need to decide what variable name to use, h or dt, and then stay with it.
It is almost certain that you need to perform more than one RK4 step, thus you need to frame them with a loop. What that loop contains in addition to the RK4 stages depends on what the output of the program is supposed to be. Also, you need to adapt the last step if the target time is not a multiple of the time step.
while(t < timepassed) {
kx1=dt*dxdt(t,x,v);
kv1=dt*dvdt(t,x,v);
kx2=dt*dxdt(t+dt/2,x+kx1/2,v+kv1/2);
kv2=dt*dvdt(t+dt/2,x+kx1/2,v+kv1/2);
kx3=dt*dxdt(t+dt/2,x+kx2/2,v+kv2/2);
kv3=dt*dvdt(t+dt/2,x+kx2/2,v+kv2/2);
kx4=dt*dxdt(t+dt,x+kx3,v+kv3);
kv4=dt*dvdt(t+dt,x+kx3,v+kv3);
t = t + dt;
x = x + (1.0/6.0)*(kx1 + 2*kx2 + 2*kx3 + kx4);
v = v + (1.0/6.0)*(kx1 + 2*kv2 + 2*kv3 + kv4);
// output for the step? Depending on the time?
}

Newton's Method in C++

I am trying to translate f(x) = x − e-(x2) in c++ source code but I keep getting errors. I have tried :
double f(double x)
{
exp = pow(-x, 2);
double result = x - exp;
return x;
};
Any insight?
If it helps, I am using Code::Blocks
#include <math.h>
double f(double x)
{
return x - exp(-(x*x));
}

Variables out of scope in main when called by reference by a function in C++

I have made the following code, whose output should generate a point uniformly at random on the unit circle centered at the origin:
#include "unif.h"
#include <iostream>
#include <cmath>
using namespace std;
void point_on_circle(double& x, double& y)
{
double r;
do
{
double x = unif(-1.,1.);
double y = unif(-1.,1.);
double r = x*x + y*y;
}
while (r >=1.0);
x = x / sqrt(r);
y = y / sqrt(r);
}
int main()
{
cout << "Pair of points on the circle found is " << x << " and " << y << endl;
cout << "Let's verify: x^2+y^2=" << x*x+y*y << endl;
return 0;
}
The header "unif.h" is just a file that contains a function void unif(double x, double y), that produces uniformly random numbers in the interval (x,y), and it works perfectly (already tested).
The problem is that when I build the program then it gives me (of course) the error in the main:
"error: 'x' was not declared in this scope"
which is clear since of course x is defined outside the main and never defined in main(). I cannot figure out how to tell the compiler that the values of x and y found by the function point_on_circle should be "carried" inside the main. How could I fix this code?
Thanks in advance
In your main method you did not declare a variable called x nor y. Moreover, you also have scoping issues in your point_on_circle(double& x, double& y) function with the variable r.
Please review C++ scoping.
Because you defined x in the do-while loop, so you cannot use it outside the loop, since those definitions hide the parameters x and y. Define it before the loop:
void point_on_circle(double& x, double& y)
{
double r;
do
{
x = unif(-1.,1.);
y = unif(-1.,1.);
r = x*x + y*y;
}while (r >=1.0);
x = x / sqrt(r);
y = y / sqrt(r);
}
You have a few issues.
1) you need to declare x and y inside main.
2) you never, ever actually call point_on_circle. At all.
3) finally, as others noted, you mask parameters x and y in your do loop.
With all of that said, it looks like you're attempting to find a random point on the unit circle. with that in mind, I would remove the do loop entirely and just do this:
void point_on_circle(double& x, double& y)
{
double r;
x = unif(-1.,1.);
y = unif(-1.,1.);
r = x*x + y*y;
x = x / sqrt(r);
y = y / sqrt(r);
}
It gives the exact same result while avoiding a (potential) endless loop, and certainly avoids useless extra processing.

In C++ finding sinx value with Taylor's Series

I am trying to write a block of codes in C++ that calculates sinX value with Taylor's series.
#include <iostream>
using namespace std;
// exp example
#include <cstdio> // printf
#include <cmath> // exp
double toRadians(double angdeg) //convert to radians to degree
{ //x is in radians
const double PI = 3.14159265358979323846;
return angdeg / 180.0 * PI;
}
double fact(double x) //factorial function
{ //Simply calculates factorial for denominator
if(x==0 || x==1)
return 1;
else
x * fact(x - 1);
}
double mySin(double x) //mySin function
{
double sum = 0.0;
for(int i = 0; i < 9; i++)
{
double top = pow(-1, i) * pow(x, 2 * i + 1); //calculation for nominator
double bottom = fact(2 * i + 1); //calculation for denominator
sum = sum + top / bottom; //1 - x^2/2! + x^4/4! - x^6/6!
}
return sum;
}
int main()
{
double param = 45, result;
result = mySin(toRadians(param)); //This is my sin value
cout << "Here is my homemade sin : " << result << endl;
result = sin(param); //This is library value
cout << "Here is the API sin : " << result << endl;
return 0;
}
So my program works without any error. My output is exactly:
Here is my homemade sin : nan
Here is the API sin:0.850904
I know I am making a big logic mistake but I couldn't find it out. It is my second week with C++. I am more familiar with Java. I coded the same thing and It worked absolutely perfect. The answers matched each other.
Thanks for your time and attention!
in fact, you miss the return: x*fact(x-1); should be return x*fact(x-1);. You can see the compiler complaining if you turn the warnings on. For example, with GCC, calling g++ -Wall program.cpp gives Warning: control reaches end of non-void function for the factorial function.
The API sin also needs the angle in radians, so change result=sin(param); into result=sin(toRadians(param));. Generally, if in doubt about the API, consult the docs, like here.
Your codes seems to have some logical mistakes. Here is my corrected one:
#include <iostream>
using namespace std;
double radians(double degrees) // converts degrees to radians
{
double radians;
double const pi = 3.14159265358979323846;
radians = (pi/180)*degrees;
return radians;
}
double factorial(int x) //calculates the factorial
{
double fact = 1;
for(; x >= 1 ; x--)
{
fact = x * fact;
}
return fact;
}
double power(double x,double n) //calculates the power of x
{
double output = 1;
while(n>0)
{
output =( x*output);
n--;
}
return output;
}
float sin(double radians) //value of sine by Taylors series
{
double a,b,c;
float result = 0;
for(int y=0 ; y!=9 ; y++)
{
a= power(-1,y);
b= power(radians,(2*y)+1);
c= factorial((2*y)+1);
result = result+ (a*b)/c;
}
return result;
}
double n,output;
int main()
{
cout<<"enter the value\t";
cin>>n;
n = radians(n);
cout<< "\nthe value in radians is\t"<< n << "\n";
output = sin(n);
cout<< "\nsine of the given value is\t"<< output;
return 0;
}
The intention of this program was to use custom functions instead of libraries to make learning for others easy.
There are four user defined functions in this program.The first three user defined functions 'radians()', 'factorial()','power()', are apparently simple functions that perform operations as their name suggests.
The fourth function 'sin()' takes input in radians given by the function 'radians()'. The sin function uses Taylors series iterated term wise in the function's 'for(int y= 0;y!=9;y++)' loop till nine iterations to calculate the output.The 'for()' loop iterates the general mathematical expression: Term(n)=((-1)^n).(x^(2n+1))/(2n+1)!
sin(x)= x- x^3/3! + x^5/5! -x^7/7! + x^9/9!
=x-x^3/2*3 (1- x^2/4*5 + x^4/4*5*6*7 + x^6/4*5*6*7*8*9)
=x - x^3/2*3 {1- x^2/4*5(1- x^2/6*7 + x^4/6*7*8*9)}
=x - x^3/2*3 [{1- x^2/4*5 ( 1- x^2/6*7 (1- x^2/8*9))}]
=x(1 - x^2/2*3 [{1- x^2/4*5 ( 1- x^2/6*7 (1- x^2/8*9))}])
double sin_series_recursion(double x, int n){
static double r=1;
if(n>1){
r=1-((x*x*r)/(n*(n-1)));
return sin_series_recursion(x,n-2);
}else return r*x;
}