I am trying to calculate Pi using this formula:
http://functions.wolfram.com/Constants/Pi/06/01/01/0005/
And this is the code:
#include <iostream>
#include <cmath>
using namespace std;
int main() {
long double n;
cin >> n;
long double first_part = 0.0, second_part = 0.0, pi = 0.0;
for(int i = 0; i <= n; i++)
{
first_part += (pow(-1, n)) / ((2 * n + 1) * pow(5, 2 * n + 1));
second_part += (pow(-1, n)) / ((2 * n + 1) * pow(239, 2 * n + 1));
}
pi = (first_part * 16) - (second_part * 4);
cout << pi << endl;
return 0;
}
But something goes wrong. For example, for n = 300 it outputs 6.65027e-420.
I really cannot find my mistake.
Please help me.
Thank you very much.
You're using the wrong variable:
for(int i = 0; i <= n; i++)
^^^^^
iterating over 'i'
But:
first_part += (pow(-1, n)) / ((2 * n + 1) * pow(5, 2 * n + 1));
second_part += (pow(-1, n)) / ((2 * n + 1) * pow(239, 2 * n + 1));
^^^^^^^^^^ ^^^^^ ^^^^^^^^^^^
all operations use 'n'
You reached the limit of floating point accuracy:
#include <cmath>
#include <iostream>
int main()
{
// This will print inf (infinite)
std::cout << std::pow(5.0, 600.0) << "\n"; // pow(5, 2 * n + 1))
return 0;
}
Change your code replacing all n to i in the for loop:
#include <iostream>
#include <cmath>
using namespace std;
int main() {
long double n;
cin >> n;
long double first_part = 0.0, second_part = 0.0, pi = 0.0;
for(int i = 0; i <= n; i++)
{
first_part += (pow(-1, i)) / ((2 * i + 1) * pow(5, 2 * i + 1));
second_part += (pow(-1, i)) / ((2 * i + 1) * pow(239, 2 * i + 1));
}
pi = (first_part * 16) - (second_part * 4);
cout << pi << endl;
return 0;
}
I ran the above code and found outout:
3.14159
Careful: pow(239, 2 * n + 1)) can overflow second_part! Because double has the range:
1.7E +/- 308 (15 digits)
Reference here.
Related
I'm trying to implement the shooting method which is used to solve 2nd-order ordinary differential equations with boundary conditions in C++. The equation is d^2y/dx^2 = 2ydy/dx. The boundary conditions provided are at x = 0, u1 =0.5 and at x = 1, u1 =1. The step size for x is 0.25. The values of U1 and U2 are being solved simultaneously at each x/iteration. However, on printing the values of U1 and U2 I get 0 as the output.
#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;
int i{0}, j{0};
double K1_one, K2_one, K3_one, K4_one, K_one;
double K1_two, K2_two, K3_two, K4_two, K_two;
double x[5] = {0, 0.25, 0.5, 0.75, 1};
double U1[5] = {0.5};
double U2[5] = {};
double G1{0}, G2{0}, G3{0};
double a{0}, b{0};
double f1(double u2)
{
return u2;
}
double f2(double u1, double u2)
{
return 2 * u1 * u2;
}
double RK4_f1(double U2[5])
{
K1_one = 0.25 * (f1(U2[i - 1]));
K2_one = 0.25 * (f1(U2[i - 1] + K1_one / 2));
K3_one = 0.25 * (f1(U2[i - 1] + K2_one / 2));
K4_one = 0.25 * (f1(U2[i - 1] + K3_one));
K_one = (K1_one + 2 * K2_one + 2 * K3_one + K4_one) / 6;
U1[i] = U1[i - 1] + K_one;
a = U1[i];
return a;
}
double RK4_f2(double U1[5], double U2[5])
{
K1_two = 0.25 * (f2(U1[i - 1], U2[i - 1]));
K2_two = 0.25 * (f2(U1[i - 1] + 0.25 / 2, U2[i - 1] + K1_two / 2));
K3_two = 0.25 * (f2(U1[i - 1] + 0.25 / 2, U2[i - 1] + K2_two / 2));
K4_two = 0.25 * (f2(U1[i - 1] + 0.25, U2[i - 1] + K3_two));
K_two = (K1_two + 2 * K2_two + 2 * K3_two + K4_two) / 6;
U2[i] = U2[i - 1] + K_two;
b = U2[i];
return b;
}
int main()
{
cout << "Enter your first random guess for u2" << endl;
cin >> G1;
U2[0] = G1;
cout << "\nu1[i]\tu2[i]\n"
<< endl;
for (int i = 1; i < 5; i++)
{
for (int j = 1; j <= 2; j++)
{
if (j == 1)
{
a = RK4_f1(U2);
}
else
{
b = RK4_f2(U1, U2);
}
}
cout << a << "\t" << b << endl;
}
cout << "Enter your second random guess for u2" << endl;
cin >> G2;
U2[0] = G2;
cout << "\nu1[i]\tu2[i]\n"
<< endl;
for (int i = 1; i < 5; i++)
{
for (int j = 1; j <= 2; j++)
{
if (j == 1)
{
a = RK4_f1(U2);
}
else
{
b = RK4_f2(U1, U2);
}
}
cout << a << "\t" << b << endl;
}
}
Here's what I have:
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
double pi = 0;
long i;
long n;
cout << "Enter the value of n: ";
cin >> n;
cout << endl;
for (i = 0; i < n; i++)
{
if (i % 2 == 0)
pi = pi + (1 / (2 * i + 1));
else
pi = pi - (1 / (2 * i + 1));
pi = 4 * pi;
}
cout << endl << "pi = " << pi << endl;
return 0;
}
However, this does not give the desired output. For example, n = 9, pi = 262144. I know it's possible to just store pi as a constant and get the result that way, but I'm wondering what I am doing wrong using the algorithm above.
Because of long i;, (1 / (2 * i + 1)) will be zero for any i>0.
When i=0, you got pi=1;
for i=1,9, you got pi = 4*pi;
That's why you got 262144 which is 4^8.
You might want
for (i = 0; i < n; i++)
{
if (i % 2 == 0)
pi = pi + (1.0 / (2 * i + 1));
else
pi = pi - (1.0 / (2 * i + 1));
}
pi = 4 * pi;
I'm solving a algorithm problem https://codeforces.com/contest/1671/problem/E. Although my submit can pass the tests provided by the contest, I find it fails on specific test(Hack). When I'm trying to find where's the error, I find that if I choose start debugging, the program would run perfectly. However, when I click "run", it would give a wrong answer. So, I'm curious about what happens.
#include<iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int const NN = 1e6;
int const MOD = 998244353;
char str[NN];
long long dfs_data[NN];
int powans[20];
string myhash[NN];
int n;
long long dfs(int num) {
if (dfs_data[num] != 0) return dfs_data[num];
if (num >= powans[n - 1] - 1) {
dfs_data[num] = 1;
return 1;
}
if (myhash[num * 2 + 1] == myhash[num * 2 + 2]) {
dfs_data[num] = (dfs(num * 2 + 1) % MOD) * (dfs(num * 2 + 2) % MOD) % MOD;
} else dfs_data[num] = 2 * (dfs(num * 2 + 1) % MOD) * (dfs(num * 2 + 2) % MOD) % MOD;
return dfs_data[num];
}
void gethashcode(int t) {
if (t >= powans[n - 1] - 1) {
myhash[t] += str[t];
return;
}
if (myhash[2 * t + 1] == "") gethashcode(2 * t + 1);
if (myhash[2 * t + 2] == "") gethashcode(2 * t + 2);
if (myhash[2 * t + 1] < myhash[2 * t + 2]) myhash[t] = str[t] + myhash[2 * t + 1] + myhash[2 * t + 2];
else myhash[t] = str[t] + myhash[2 * t + 2] + myhash[2 * t + 1];
}
void solve() {
memset(dfs_data, 0, sizeof dfs_data);
cin >> n;
cin >> str;
powans[0] = 1;
for (int i = 1; i < 19; i++) {
powans[i] = 2 * powans[i - 1];
}
for (int i = 0; i < NN; i++) {
myhash[i] = "";
}
gethashcode(0);
cout << dfs(0);
}
int main() {
solve();
}
I'm trying to recreate computation of a SIR model as described here, with extra midpoint calculations. But for some reason no values actually change during the Euler calculations.
#include <iostream>
using namespace std;
int main(){
double s[100];
double i[100];
double r[100];
double bb = 1/2;
double kk = 1/3;
s[0] = 1;
i[0] = 1.27e-6;
r[0] = 0;
int h = 1;
int max = 20;
for (int j = 0; j < max; j += h){
s[j + 1] = s[j] - h*(bb * s[j] * i[j]);
i[j + 1] = i[j] + h*(bb * s[j] * i[j] - kk * i[j]);
r[j + 1] = r[j] + h*(kk * i[j]);
cout << j << "\t" << s[j] << "\t" << i[j] << "\t" << r[j] << "\n";
/*
s[j + 1] = s[j] - 0.5*h*(bb * s[j] * i[j] + bb * s[j+1] * i[j+1]);
i[j + 1] = i[j] + 0.5*h*(bb * s[j] * i[j] - kk * i[j] + bb * s[j+1] * i[j+1] - kk * i[j+1]);
r[j + 1] = r[j] + 0.5*h*(kk * i[j] + kk * i[j+1]);
*/
}
}
Your variables bb and kk are both zero due to integer division. Always use double literals:
double bb = 1.0/2.0;
double kk = 1.0/3.0;
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))