How to code a sin progression with c? [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I'm pretty new in coding and trying to write a sin progression for the uni
As a formula it looks like this:
So I tried to code it... And somehow, it calculates the radian but not the sinus... What is wrong?
#include "stdafx.h"
#include <iostream>
#include <math.h>
using namespace std;
double n, a;
int fakultaet(double a = 2 * n + 1)
{
if (a == 0)
return 1;
else
return (a * fakultaet(a - 1));
}
int _tmain(int argc, _TCHAR* argv[])
{
double sin, y, f; // sin = Sinus, y= angle, n=index
printf("please insert the angle \n");
scanf("%lf", &y);
double x = y * 3.14159265359 * 1 / 180; // x = radian measure
while (n < 5)
{
sin = pow(-1, n) * pow(x, 2 * n + 1) / fakultaet(a);
}
printf("The sinus is %lf\n", sin);
system("Pause");
return 0;
}

You are not incrementing the sin, or the n. Also hardcoding the entry value for the factorial is not good.
It should look more like this:
#include "stdafx.h"
#include <iostream>
#include <math.h>
using namespace std;
int fakultaet(double a)
{
if (a == 0)
return 1;
else
return (a * fakultaet(a - 1));
}
int main()
{
double sin = 0, y, f; // sin = Sinus, y= angle, n=index
printf("please insert the angle \n");
scanf("%lf", &y);
double x = y * 3.14159265359 * 1 / 180; // x = radian measure
for (int n = 0; n < 5; ++n)
{
sin += pow(-1, n) * pow(x, 2 * n + 1) / fakultaet(2 * n + 1);
}
printf("The sinus is %lf\n", sin);
system("Pause");
return 0;
}
I made several edits. I turned the factorial function:
int fakultaet(double a = 2 * n + 1)
into an non hardcoded version:
int fakultaet(double a)
Added the sin initialization:
double sin = 0
Changed your while loop:
while (n < 5)
Into a for which includes the increment that was missing as well:
for (int n = 0; n < 5; ++n)
Also turned the sin calculation:
sin = pow(-1, n) * pow(x, 2 * n + 1) / fakultaet(a);
Into one that sums:
sin += pow(-1, n) * pow(x, 2 * n + 1) / fakultaet(2 * n + 1);

You can get a neater and more efficient result by observing that
adjacent terms in the sum are related. We can express this as a recurrence:
T_n = - T_{n-1} x^2 /((2n+1) (2n))
T_0 = x
This is better since it avoids calls to pow and the need to make any explicit factorial calculations (fakultaet).
The code looks something like:
int main() {
...
double T = x;
double sin = T;
for(int i=1 ; i<5; ++i) {
T *= -(x*x) / ((2*i+1)*(2*i));
sin += T;
}
...
}

Related

Lennard-Jones / WCA Potential Simulation

i am trying to implement a molecular dynamics simulation with the Lennard Jones potential.
I have the time evolution of the positions and velocities of the particles in multiple config files (n = 0,...,99) in steps of dt, such that t=n dt. So the actual simulation part is taken care of in that sense, for now i only have to calculate the potential energy and the force on each particle.
I already implemented a function to read in the config.dat files and put them in vectors, that part works as far as i know without an error. Then i wrote functions that calculate the force and the potential energy with a given distance r_ij between two particles (also used Newtown's third law so that i don't have to calculate the forces multiple times for the same interaction).
I also (hopefully correctly) implemented the periodic boundary conditions so that the particles can interact with their own images in the image boxes.
To test if my code works, i wanted to plot the total potential energy for all t=n dt.
However that does not work as intended because for some reason the potential energy that is written into the output files is always zero (the function for the potential energy returns zero if r_ij > r_cut, r_cut is where the potential is set to zero).
#include <iostream>
#include <math.h>
#include <fstream>
#include <stdlib.h>
#include <vector>
#include <string>
#include <utility>
#include <stdexcept>
#include <sstream>
using namespace std;
// Python >> C/C++
// Reads the initial states from the files
// The whole simulation in Python would have been as long as the function in c++ that just reads in the input
void read_input(int num_file, vector<double>& n, vector<double>& x, vector<double>& y, vector<double>& vx, vector<double>& vy, double& lx, double& ly) {
// Variable file name + opening it
ifstream file("configurations/config_" + to_string(num_file) + ".dat");
// Temp variables for reading in the file
double num, temp_x, temp_y, temp_vx, temp_vy;
// Looping over it
if (file.is_open()) {
string line;
while (getline(file, line)) {
// For the header; The header contains only the dimensions, e.g, 14 14, there are only 5 characters
if (line.length() == 5) {
stringstream dim_str(line);
dim_str >> lx >> ly;
continue;
}
// For the rest files
stringstream temp_str(line);
temp_str >> num >> temp_x >> temp_y >> temp_vx >> temp_vy;
n.push_back(num);
x.push_back(temp_x);
y.push_back(temp_y);
vx.push_back(temp_vx);
vy.push_back(temp_vy);
}
file.close();
}
}
// Calculates the potential for rij
double calc_pot(double r) {
double sigma = 1.0;
double epsilon = 1.0;
if (r <= pow(2, (1.0 / 6)) * sigma) {
double res = 4.0 * epsilon * (pow(sigma / r, 12) - pow(sigma / r, 6)) + epsilon;
return res;
}
else {
return 0;
}
}
// Calculates the force for rij
double calc_force(double r) {
double sigma = 1.0;
// Replaced the sigma^n with 1 bcs sigma = 1
double epsilon = 1.0;
if (r <= pow(2, (1.0 / 6)) * sigma) {
double res = (48.0 * epsilon / pow(r, 13)) - (24 * epsilon / pow(r, 7));
return res;
}
else {
return 0;
}
}
// Calculates the distance of the
double dist(double rx, double ry) {
return sqrt(rx * rx + ry * ry);
}
int main() {
// Misc. parameters
int N = 144;
double mass = 1.0;
double sigma = 1.0;
double epsilon = 1.0;
// Tau = sqrt(mass*sigma^2/epsilon) = (here) 1
double tau = 1.0;
double dt = 0.02;
// Vectors for the read in values for i and i+1
vector<double> n, x, y, vx, vy;
double lx, ly;
// Vector for the potential and two for the force, x and y
vector<double> epot(N), f_x(N), f_y(N);
for (int i = 0; i < N; i++) {
epot[i], f_x[i], f_y[i] = 0;
}
// Outerloop for time steps (in this case the files n = {0,..,99})
for (int k = 0; k <= 99; k++) {
string fname = "output/epot_" + to_string(k) + ".txt";
ofstream output(fname);
read_input(k, n, x, y, vx, vy, lx, ly);
// Inner two loops to accses every possible interaction without doing them twice
for (int i = 0; i < N - 1; i++) {
// Vecctor for particle i
double rix = x[i];
double riy = y[i];
for (int j = i + 1; j < N; j++) {
// Vector for particle i+1
double rjx = x[j];
double rjy = y[j];
// Periodic boundary cond.
if (rix > lx) {
rix -= lx;
}
if (riy > ly) {
riy -= ly;
}
if (rjx > lx) {
rjx -= lx;
}
if (rjy > ly) {
rjy -= ly;
}
if (rix < 0) {
rix += lx;
}
if (riy < 0) {
riy += ly;
}
if (rjx < 0) {
rjx += lx;
}
if (rjy < 0) {
rjy += ly;
}
// Component wise distance for the force
double dist_x = rix - rjx;
double dist_y = riy - rjy;
// Minimum image convention
if (abs(dist_x) > lx / 2) {
dist_x = (lx - abs(dist_x)) * (-dist_x) / abs(dist_x);
}
if (abs(dist_y) > ly / 2) {
dist_y = (ly - abs(dist_y)) * (-dist_y) / abs(dist_y);
}
// Normalized Force/R
f_x[i] += calc_force(dist_x) * (1 / dist(dist_x, dist_y));
f_y[i] += calc_force(dist_y) * (1 / dist(dist_x, dist_y));
f_y[j] += -calc_force(dist_x) * (1 / dist(dist_x, dist_y));
f_y[j] += -calc_force(dist_y) * (1 / dist(dist_x, dist_y));
// Potential energy
epot[i] += calc_pot(dist(dist_x, dist_y));
}
// Potential energy per particle
output << fixed << std::setprecision(4) << epot[i] / (N) << endl;
}
}
}
A config file looks something like this
14 14
0 0 0 1.0292605474705 0.394157727758591
1 0 1.16666666666667 1.05721528014223 1.9850461002085
2 0 2.33333333333333 1.18385526103892 0.143930912297367
3 0 3.5 -0.938850340823852 1.71993225409788
4 0 4.66666666666667 1.99468650405917 0.952210892864475
5 0 5.83333333333333 -0.985361963654284 3.05201529674118
6 0 7 2.84071317501321 0.0689241023507716
7 0 8.16666666666667 3.56152464385237 2.88858201933488
8 0 9.33333333333333 0.147896423269195 1.40592679110988
The header contains the dimensions of the simulation box, here (14,14).
Then all the lines have the corresponding values of {#Particle, x, y, velocity x, Velocity y).
The file above shows this for the first 9 particles.
I am relatively new to c/c++ so have mercy with me 😄.
Also i am aware that the code has still potential to be optimised but i will deal with that when i can calculate the force on each particle correctly.
Edit:
Here is the formula for the potential energy:
The force can be calculated via F= -d/dr U(r).

how do I replace pow()?

how do I replace the pow() function in two cases in my code ?
I think this can be done with a for loop
#include <iostream>
#include <cmath>
using namespace std;
int main(){
double a, b, h, PI = 3.141592;
int n;
cin >> a >> b >> h >> n;
for (double x = a; x <= b; x += h) {
double ans = 1, y;
for (int k = 0; k <= n; k++) {
ans *= cos(k * PI / 4) * pow(x, k);
for (int i = 2; i <= k; i++) {
ans /= i;
}
}
y = pow(exp(cos(x * sin(PI / 4))), x * cos(PI / 4));
cout << ans << " " << y << " " << fabs(y-ans) << endl;
}
return 0;
}
Do not write everything in main.
Define double S(double x, int n) and double U(double x).
each element of sum can be calculated based on previous element.
cos(k * M_PI / 4) has repeating values so it can be stored in table.
double S(double x, int n)
{
double a = 1;
double s = a;
constexpr double q = std::cos(M_PI / 4);
constexpr double cos_val[]{ 1, q, 0, -q, -1, -q, 0, q };
for (int k = 1; k <= n; ++k) {
a *= x / k;
s += cos_val[k & 7] * a
}
return s;
}
For the inner loop, you need not calculate the power in each iteration if you consider that on the previous iteration you already calculated pow(x,k-1) and that pow(x,k) == pow(x,k-1)*x:
double pow_x = 1; // on first iteration pow(x,0) == 1
for (int k = 0; k <= n; k++) {
ans *= cos(k * PI / 4) * pow_x;
// ...
pow_x *= x; // pow(x,k) -> pow(x,k+1)
}
The second use of pow in your code cannot be easily replaced, because of the floating point exponent. You would have to rewrite pow to get the same result. However, your code does not match the formula in the image. The image says (pseudo maths notation):
e ^ ( x * C1 ) * C2
your code is calculating
y = pow(exp(cos(x * sin(PI / 4))), x * cos(PI / 4));
( e^(C2) ) ^ (x * C1)
change it to
y = exp(x * cos(PI / 4)) * cos(x * sin(PI / 4))

How do I fix this bug with arctanx function in c++

I've recently been given a problem by my teacher about some mathematical equation / formula called the arctanx formula. The question is:
According to the Arctanx(x) = x - ((x ^ 3) / 3) + ((x ^ 5) / 5) - ((x ^
7) / 7) + ...and π = 6 * arctanx(1 / sqrt(3)), Create function arctanx(x)
, and find pi when the last "number"(like this ((x ^ y) / y)) is right before
and bigger than 10 ^ -6, or you can say that no "number" can be smaller than
that number without being smaller than 10 ^ -6.
I tried to code it out, but there is a bug in it.
# include<iostream>
# include<math.h>
using namespace std;
float arctanx() {
long double pi = 3.1415926535897;
int i = 0; // 0 = +, 1 = -
float sum = 0;
float lsum;
for (int y = 1; y < pi; y += 2) {
if (lsum > 0.000001) {
if (i == 0) {
lsum = pow(1 / sqrt(3), y) / y;
sum += pow(1 / sqrt(3), y) / y;
i++;
} else if (i == 1) {
lsum = pow(1 / sqrt(3), y) / y;
sum -= pow(1 / sqrt(3), y) / y;
i--;
}
} else {
break;
}
}
sum = sum * 6;
return sum;
}
int main() {
cout << arctanx();
return 0;
}
It should have a output of some number not equal to zero, but I got 0 from running this.
Your program has Undefined Behavior because you are using the uninitialized float lsum; in the comparison if (lsum > 0.000001).
What probably happens in your case is that lsum happens to be less than or equal to 0.000001 and your for immediately breaks without doing anything causing your function to return 0 * 6 which is obviously 0.
Create function arctanx(x)
The function defined in the posted code doesn't accept any parameter, it just uses the hardwired (and repeated) value 1 / sqrt(3) and tries to return an approximated value of π instead of the arctangent of x.
It also has undefined behavior, beeing lsum uninitialized (therefore having an indeterminate value) when it is first used in the comparison inside the loop.
Consider this implementation, but be advised that this particular polinomial expansion diverges for values of x greater than 1.
#include <iostream>
#include <iomanip>
#include <cmath>
double arctanx(double x);
int main()
{
double pi = 6.0 * arctanx(1.0 / std::sqrt(3));
std::cout << std::setprecision(8) << pi << '\n';
}
double arctanx(double x)
{
// You can take advantage of a running power, instad of calculating
// pow(x, i) at every iteration
double sq_x = x * x;
double pow_x = x * sq_x;
double err = 1e-6;
// Instead of keeping track of the alternating sign, you can use
// two separate partial sums
double sum_pos_term = x;
double sum_neg_term = 0.0;
for (int i = 3; i < 33; i += 2) // <- Limit the number of iterations
{
if (pow_x < err * i)
break;
sum_neg_term += pow_x / i;
i += 2;
pow_x *= sq_x;
if (pow_x < err * i)
break;
sum_pos_term += pow_x / i;
pow_x *= sq_x;
}
return sum_pos_term - sum_neg_term;
}

Trapezoidal integration program doesn't return a reasonable value

Why doesn't this code to integrate the area under a sin curve return a reasonable value? (edited to include a bunch of suggestions)
//I want to write a program that takes the area under a curve by outputting the sum of the areas of n rectangles
#include <vector>
#include <iostream>
#include <cmath>
#include <numeric>
double interval(double d, double n)
{
return d / n;
}
using namespace std;
int main()
{
double xmax = 20; //upper bound
double xmin = 2; //lower bound
double line_length = xmax - xmin; //range of curve
double n = 1000; //number of rectangles
vector<double> areas;
double interval_length = interval(line_length, n);
for (double i = 0; i < n; ++i)
{
double fvalue = xmin + i;
areas.push_back((interval_length * sin(fvalue)) + (0.5 * interval_length * (sin(fvalue + 1) - sin(fvalue))));
//idea is to use A = b*h1 + 1/2 b*h2 to approximate the area under a curve using trapezoid area
}
I added fvalue, interval_length and fixed the logic a bit
double sum_areas = accumulate(areas.begin(), areas.end(), 0.0);
//accumulate takes each element in areas and adds them together, beginning with double 0.0
cout << "The approximate area under the curve is " << '\n';
cout << sum_areas << '\n';
//this program outputs the value 0.353875, the actual value is -.82423
return 0;
}
The code below doesn't mix using loop variable and x. It has a drawback (same as yours code) that error summing dx is accumulated i.e. dx*n != xmax-xmin. To account for this particular error one should calculate current x as function of i (loop variable) on each iteration as x = xmin + (xmax - xmin)*i/n.
#include <iostream>
#include <cmath>
double sum(double xmin, double xmax, double dx)
{
double rv = 0;
for (double x = xmin + dx; x <= xmax; x += dx)
rv += (sin(x) + sin(x-dx)) * dx / 2;
return rv;
}
int main()
{
int n = 1000;
double xmin = 0;
double xmax = 3.1415926;
std::cout << sum(xmin, xmax, (xmax - xmin)/n) << std::endl;
return 0;
}
You are forgetting the interval length in the function argument
double fvalue = xmin + i;
areas.push_back((interval_length * sin(fvalue)) + (0.5 * interval_length * (sin(fvalue + 1) - sin(fvalue))));
Should instead be
double fvalue = xmin + i*interval_length;
areas.push_back((interval_length * sin(fvalue)) + (0.5 * interval_length * (sin(fvalue + interval_length) - sin(fvalue))));
The second line can be better written as
areas.push_back(interval_length * 0.5 * (sin(fvalue + interval_length) + sin(fvalue));

How do I express this?

I'm trying to work out how to write the following:
total = (value * 0.95 ^ 0) + (value * 0.95 ^ 1) + (value * 0.95 ^ 2) ...
or:
x = (y * z ^ 0) + (y * z ^ 1) + (y * z ^ 2) + (y * z ^ 3) ...
This expresses how to calculate x for 4 iterations, but how can I express this to work with a variable number of iterations? Obviously I could create a loop and add the values together, but I'd really like to find a single equation that solves this.
I'm using c++ but I guess this isn't really a language specific problem (sorry I literally don't know where else to ask this question!).
Any ideas?
Thanks,
Chris.
There is no need for a loop here, you "just" need to employ some maths.
Note that you can rewrite that as
y * (z0 + z1 + ... + zn)
Now, the series
z0 + z1 + ... + zn
sums to
(z(n+1) - 1) / (z - 1)
so your equation would be
x = y * (z(n+1) - 1) / (z - 1)
Equation-wise solving, this is a geometric series and can therefore be calculated with
double geometric_series(double y, double z, int N) {
return y * (std::pow(z, N) - 1.0) / (z - 1.0);
}
but the same result can be obtained with some fun C++ metaprogramming: if you know the number of iterations in advanced and you're allowed to use C++17 features and fold expressions you could do as follows
template<std::size_t... N>
double calculate_x(double y, double z, std::index_sequence<N...>) { // [0;N[
auto f = [](double y_p, double z_p, double exp) {
return y_p * std::pow(z_p, exp);
};
return (f(y, z, N) + ...);
}
template <std::size_t N>
auto calculate_x(double y, double z) {
return calculate_x(y, z, std::make_index_sequence<N>{});
}
Alternatively this can also be done with pre-C++17 templates
template <int N>
double calculate_x(double y, double z) {
return calculate_x<N-1>(y, z) + (y * std::pow(z, N - 1));
}
template <>
double calculate_x<0>(double, double) {
return 0;
}
Otherwise a simpler solution would be to just use a loop
double calculate_x_simple(double y, double z, int N) {
double ret = 0.0;
for (int i = 0 ; i < N ; ++i)
ret += y * std::pow(z, i);
return ret;
}
Driver for the code above
int main() {
// x = (y * z ^ 0) + (y * z ^ 1) + (y * z ^ 2) + (y * z ^ 3)
double y = 42.0;
double z = 44.5;
std::cout << (calculate_x<3>(y, z) == calculate_x_simple(y, z, 3)); // 1
}
As you mentioned, it seems reasonable to use a loop. But if you know the amount of iterations at compile time, you could use templates like this:
template <int n>
double foo(double y, double z)
{
return foo<n-1>(y, z) + y * std::pow(z, n);
}
template <>
double foo<-1>(double, double)
{
return 0;
}
With just a little bit of optimisation this will unfold to a single equation.
Example:
#include <iostream>
#include <cmath>
template <int n>
double foo(double y, double z)
{
return foo<n-1>(y, z) + y * std::pow(z, n);
}
template <>
double foo<-1>(double, double)
{
return 0;
}
int main()
{
std::cout << foo<2>(2,3) << std::endl;
}
Output: 26
If a loop would be the only option:
double x = 0;
int n = 5;
for(int exponent = 0; exponent <= n; ++exponent)
x += y*pow(z, exponent);
you can just use math.pow function with a for loop
#include <stdio.h>
#include <math.h>
int main(void) {
int i;
int n = 5;
double y = 0.5;
double z = 0.3;
double answer = 0;
for (i = 0 ; i < n ; i++)
answer += y * pow(z,i);
printf("%f", answer);
return 0;
}
It can be expressed as a sum from n=0 to m. It can be expressed in a single formula, according to wolframalpha.
Don't know if this fulfills your purpose, but you can use recursion(which in real terms is a loop only :) )
int x = evaluate(y, z, count);
int evaluate(y,z, count)
{
if (count <= 0)
return 0;
return (evaluate(y, z, count-1) + y*z^count);
}
Using n as the number of iterations,
#include <cmath>
double foo(double y, double z, int n)
{
double x =0;
for(int i = 0 ; i<n; ++i){
x+=y*std::pow(z,i);
}
return x;
}
Where std::pow is the power function.