I need to increase/reduce phi angle by value d infinitely. (d can be negative or positive).
"Infinitely" means that cycling change can happen as much as long. But to avoid overflowing it is necessary "drop" value, relying on periodicity of sin () and cos (). (0 <=> 2*pi <=> 2*n*pi).
How it can be implemented in function? (e.g. double stepAngle(double phi, double d)).
The standard library functions just "do the right thing" for values > 2*pi, you don't have to do anything:
int main() {
double pi = 3.14159265359;
double x = 2.5;
cout << sin(x) << endl;
cout << sin(x + 2*pi) << endl;
cout << sin(x - 8*pi) << endl;
}
These will all print the same value; try it out.
This is possible with fmod fairly easily.
double stepAngle(double phi, double d)
{
double newPhi = phi += fmod(2*pi, d);
if(newPhi > 2*pi)
{
newPhi -= 2*pi;
}
if(newPhi < 0)
{
newPhi += 2*pi;
}
return newPhi;
One approach is to renormalize to the desired range:
while (d > 2*pi) d -= 2*pi;
while (d < 0) d += 2*pi;
That will be efficient as long as d is not extremely far outside the range of 0..2*pi.
Related
/*I need to use the result from the (delta) function inside the (sol_ec_II) function for a school assignment.*/
#include <iostream>
#include <ctgmath>
using namespace std;
double delta(double a, double b, double c) {
return (b * b) - (4 * a * c);/* so I need to take this value [(b * b) - (4 * a * c)]
and use it in sol_ec_II in the places where I wrote "delta". */
}
void sol_ec_II(double a, double b, double c) {
if (delta < 0) {//here
cout << endl << "Polinomul NU are solutii.";
}
else {
double x1 = -1 * b - sqrt(delta);//here
double x2 = -1 * b + sqrt(delta);//here
}
}
// I would also need to use the (delta) function inside the (sol_ec_II) so they use the same
a, b, c values like this:
void sol_ec_II(double a, double b, double c) {
delta(a, b, c);
if (delta < 0) {
cout << endl << "Polinomul NU are solutii.";
}
else {
double x1 = -1 * b - sqrt(delta);
double x2 = -1 * b + sqrt(delta);
}
}
//so I don't understand how to get the value that results from delta(a, b, c) and use it inside the if statement and sqrt.
The result "comes out" of the function call at the time you call it. Look, you already know how sqrt works. sqrt is a function! You write sqrt(something) and that calls the function sqrt and it calls the function sqrt with the argument something and then the return value from sqrt gets used in the place where you wrote sqrt(something). e.g. 1 + sqrt(4) calculates 3.
Likewise the return value from delta gets used in the place where you wrote delta(a, b, c). If you want to call delta and then call sqrt (i.e. calculate the square root of the delta) you write sqrt(delta(a, b, c)).
Obviously, just calculating a number is pretty useless. You probably want to do something with the number, like saving it in a variable or printing it. Examples:
cout << "the square root of the delta is " << sqrt(delta(a,b,c)) << endl;
cout << "the delta plus one is " << (delta(a,b,c) + 1) << endl;
double the_delta = delta(a,b,c);
cout << "the delta is " << the_delta << " and the square root of the delta is " << sqrt(the_delta) << endl;
if (delta(a,b,c) < 0)
cout << "the delta is negative" << endl;
else
cout << "the delta isn't negative" << endl;
Note: Every time the computer runs delta(a,b,c) it calls the delta function. It doesn't remember the calculation from last time. You can see this because if you put cout instructions inside the delta function, they get printed every time the computer runs delta(a,b,c).
Of course I will not give you the solution for your program. I hope this helps you understand how functions work.
here you should pass parameters to deleta function in order to execute it:
void sol_ec_II(double a, double b, double c) {
if (delta(a,b,c) < 0) {//here
cout << endl << "Polinomul NU are solutii.";
}
else {
double x1 = -1 * b - sqrt(delta);//here
double x2 = -1 * b + sqrt(delta);//here
}
}
or you could save the result in a new variable called result for example, and after that use it, like that:
void sol_ec_II(double a, double b, double c) {
double result = delta(a,b,c);
if (result < 0) {//here
cout << endl << "Polinomul NU are solutii.";
}
else {
double x1 = -1 * b - sqrt(delta);//here
double x2 = -1 * b + sqrt(delta);//here
}
}
The Same thing for the second function, always to execute a function use parenthesis and pass between them the arguments that the function expects.
To reuse the value you get from calling a function multiple time use a variable:
double delta(double,double,double) { return 1.2; /*ignore this for now*/ }
void sol_ec_II(double a, double b, double c) {
const auto kDelta = delta(a, b, c);
if (kDelta < 0.0) {
// do stuff
} else {
const auto kRootD = sqrt(kDelta); // same idea
const auto x1 = -b - kRootD;
const auto x2 = -b + kRootD;
// use the variables
}
}
I use auto out of habit, you don't need to, double is fine.
I would like to ask a very short question, and it is as follows: in finding the cube root of a number (both neg. and pos.) in C++, how does one restrict the output to real solutions only?
I am currently writing a program to solve a cubic with Cardano's formula, and one of the intermediate variables I am using randomly outputs the complex and real cube roots - and I only need the real roots.
(E.g. in evaluating the cube root of -0.0127378, the three roots would be 0.11677095+0.202253218i, −0.2335419, 0.11677095−0.202253218i - I wish to ignore the complex ones for substitution into a later formula)
Thank you!
EDIT: Solved it! :) I created a signum function and tweaked the sign after taking the power of the absolute value of SPrime and TPrime, so now it carries forward only the real cube root.
/* ... */
#include <iostream>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cassert>
using namespace std;
int signum(std::complex<double> z)
{
if (z.real() < 0 || z.imag() < 0) return -1;
else if (z.real() >= 0 || z.imag() >= 0) return 1;
}
// POST: The function is intended to solve a cubic equation with coefficients a, b, c and d., such that
// ax^3 + bx^2 + cx + d = 0. If there exist infinitely many solutions, we output -1, i.e. if a=b=c=d=0
// (trivial solution).
void solve(std::complex<double> a, std::complex<double> b, std::complex<double> c, std::complex<double> d, std::complex<double>& x1, std::complex<double>& x2, std::complex<double>& x3)
{
complex<double> i = complex<double> (0, 1.0);
// Consider implementing Cardano's method for obtaining the solution of a degree 3 polynomial, as suggested
// We must hence define the discriminant D of such an equation through complex doubles Q and R
std::complex<double> Q;
Q = (3.0*a*c - pow(b, 2)) / (9.0*pow(a, 2));
cout << "Q=" << Q << endl;
std::complex<double> R;
R = (9.0*a*b*c - 27.0*d*pow(a, 2) - 2.0*pow(b, 3)) / (54.0*pow(a, 3));
cout << "R=" << R << endl;
std::complex<double> D;
D = pow(Q, 3) + pow(R, 2);
// Possible types of output for discriminant
if (abs(D) < 0.0)
{
cout << "The cubic has three distinct, real roots." << endl;
}
else if (abs(D) == 0.0)
{
cout << "The cubic has three real roots, at least two of which are equal." << endl;
}
else if (abs(D) > 0.0)
{
cout << "The cubic has one real root and two complex conjugate roots." << endl;
}
// Defining two further complex double variables S and T, which are required to obtain the final solution for x1, x2 and x3
std::complex<double> S;
std::complex<double> SPrime;
SPrime = R+sqrt(Q*Q*Q + R*R);
cout << "SPrime=" << SPrime << endl;
if (signum(SPrime) == -1)
{
S = (-1)*pow(abs(SPrime), 0.3333333333333);
}
else if (signum(SPrime) == 1)
{
S = pow(abs(SPrime), 0.3333333333333);
}
cout << "S=" << S << endl;
std::complex<double> T;
std::complex<double> TPrime;
TPrime = (R-sqrt(Q*Q*Q + R*R));
if (signum(TPrime) == -1)
{
T = (-1)*pow(abs(TPrime), 0.3333333333333);
}
else if (signum(TPrime) == 1)
{
T = pow(abs(TPrime), 0.3333333333333);
}
cout << "T=" << T << endl;
cout << "TPrime= " << TPrime << endl;
// Expressions for the solutions
x1 = S + T - (b/(3.0*a));
x2 = (-0.5)*(S + T) - (b/(3.0*a)) + (sqrt(3.0)*0.5)*(S - T)*i;
x3 = conj(x2);
if (abs(x1) < 0.000000000001)
{
x1 = 0;
}
}
// Driver code
int main ()
{
// Taking user input for a, b, c and d
std::complex<double> a, b, c, d, x1, x2, x3;
cout << "Please enter the coefficients of the polynomial in successive order." << endl;
cin >> a >> b >> c >> d;
solve (a, b, c, d, x1, x2, x3);
cout << x1 << ", " << x2 << ", " << x3 << "." << endl;
return 0;
}
The problem as you're stating it can be solved trivially (with real numbers the cubic root of -x is the opposite of the cubic root of x):
double cuberoot(double x) {
if (x < 0) {
return -pow(-x, 1.0/3.0);
} else if (x > 0) {
return pow(x, 1.0/3.0);
} else {
return 0;
}
}
If the input is instead in general complex z and you're looking for the "most real" (principal) cubic root the same reasoning can be applied using complex pow version to either z or -z depending on the sign of the real part:
std::complex<double> cuberoot(std::complex<double> z) {
if (z.real() < 0) {
return -pow(-z, 1.0/3.0);
} else {
return pow(z, 1.0/3.0);
}
}
Problems with your code:
As you allow complex coefficients, the discussion of the discriminant becomes slightly meaningless, it is only of value for real coefficients.
abs(D) is always non-negative. If D==0, then there is a double root, more can not be said in the case of complex coefficients.
You can avoid a lot of code by utilizing that S*T=-Q. One would have to care that the computation of u=T^3 returns the larger of the roots of 0==u^2 - 2*R*u - Q^3 or (u-R)^2 = D = R^2+Q^3
rtD = sqrt(D);
T = cuberoot( R + (abs(R+rtD)>=abs(R-rtD)) ? rtD : -rtD );
S = (abs(T)<epsilon) ? 0 : -Q/T;
Because of abs(R)<=abs(T)^3 and abs(D)<=abs(T)^6
one gets also abs(Q)<=2^(1/3)*abs(T)^2 resulting in
abs(S)=abs(Q/T) <= 2^(1/3)*abs(T)
For S=-Q/T to fail one would thus need a serious case
of extremely small floating point numbers in R, Q
and thus T. Quantitatively, for double even
the threshold epsilon=1e-150 should be safe.
On cube root variants:
For esthetic reasons one might want T as close to a coordinate axis as possible. A cube root function achieving this would be
std::complex<double> cuberoot(std::complex<double> z) {
double r=abs(z), phi=arg(z);
double k = round(2*phi/pi);
// closest multiple of pi/2
// an equivalent angle is (phi-k*pi/2) - k*3*pi/2
return std::polar( pow(r,1.0/3), (phi-k*pi/2)/3 - k*pi/2 );
}
so that abs(phi-k*pi/2)<=pi/4, and thus the angle to the next coordinate axis of the cube root is smaller than pi/12=15°. cuberoot(i) returns -i, cuberoot(-1) returns -1, a point at 60° returns a cube root at (60°-90°)/3-90°=-100°, etc.
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 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;
}
I have this static method, it receives a double and "cuts" its fractional tail leaving two digits after the dot. works almost all the time. I have noticed that when
it receives 2.3 it turns it to 2.29. This does not happen for 0.3, 1.3, 3.3, 4.3 and 102.3.
Code basically multiplies the number by 100 uses modf divides the integer value by 100 and returns it.
Here the code catches this one specific number and prints out:
static double dRound(double number) {
bool c = false;
if (number == 2.3)
c = true;
int factor = pow(10, 2);
number *= factor;
if (c) {
cout << " number *= factor : " << number << endl;
//number = 230;// When this is not marked as comment the code works well.
}
double returnVal;
if (c){
cout << " fractional : " << modf(number, &returnVal) << endl;
cout << " integer : " <<returnVal << endl;
}
modf(number, &returnVal);
return returnVal / factor;
}
it prints out:
number *= factor : 230
fractional : 1
integer : 229
Does anybody know why this is happening and how can i fix this?
Thank you, and have a great weekend.
Remember floating point number cannot represent decimal numbers exactly. 2.3 * 100 actually gives 229.99999999999997. Thus modf returns 229 and 0.9999999999999716.
However, cout's format will only display floating point numbers to 6 decimal places by default. So the 0.9999999999999716 is shown as 1.
You could use (roughly) the upper error limit that a value represents in floating point to avoid the 2.3 error:
#include <cmath>
#include <limits>
static double dRound(double d) {
double inf = copysign(std::numeric_limits<double>::infinity(), d);
double theNumberAfter = nextafter(d, inf);
double epsilon = theNumberAfter - d;
int factor = 100;
d *= factor;
epsilon *= factor/2;
d += epsilon;
double returnVal;
modf(number, &returnVal);
return returnVal / factor;
}
Result: http://www.ideone.com/ywmua
Here is a way without rounding:
double double_cut(double d)
{
long long x = d * 100;
return x/100.0;
}
Even if you want rounding according to 3rd digit after decimal point, here is a solution:
double double_cut_round(double d)
{
long long x = d * 1000;
if (x > 0)
x += 5;
else
x -= 5;
return x / 1000.0;
}