I posted not long ago on how to compute the sum of Pi with openmp. But it seems something's off with my code. Because manually I get the right result, but when I program it, it gives wrong results, if someone can help me?
PS : s= 1/N
#include <chrono>
#include <iostream>
double f(double x)
{
return (4 / (1 + (x * x)));
}
int main()
{
int i;
const int N = 60;
double s1=0.0; double s2=0.0; double s3=0.0;
double pi = 0.0; double s4=0.0; double s5=0.0;
for (int i=0; i<N; i++)
{
//pi+=((f(i/N)+f((i+1)/N))/2*N);
s1 = f(i/N);
s2 = f((i+1)/N);
s3 = 2 * N;
s4 = s1 + s2;
s5 = s4 / s3;
pi+=s5;
}
printf("Pi = %f",pi);
return 0;
}
The reason the value is different is because variable 'i' as well as 'N' are int's. When dividing int by int the answer will always be int.
Easiest and fastest fix is to change one of the variables to a double eg.:
#include <chrono>
#include <iostream>
double f(double x)
{
return (4 / (1 + (x * x)));
}
int main()
{
const int N = 60;
double s1=0.0; double s2=0.0; double s3=0.0;
double pi = 0.0; double s4=0.0; double s5=0.0;
for (double i=0; i<N; i++) // i changed the int to double for the 'i' declaration
{
//pi+=((f(i/N)+f((i+1)/N))/2*N);
s1 = f(i/N);
s2 = f((i+1)/N);
s3 = 2 * N;
s4 = s1 + s2;
s5 = s4 / s3;
pi+=s5;
}
//printf("Pi = %f",pi);
std::cout << "Pi = " << pi << std::endl;
return 0;
}
Also since you're programming in c++ make sure to pick the better c++ alternative to some of the code:
printf is C. It still works but c++'s cout is a better alternative that's improved and safer in most cases.
You also have an extra unneeded variable declaration. You're creating two 'i' variables. Once at the start and once in the loop.
As I got it from the answers, the problem was in (i/N). Since the i int declared as an int we need to add ((double)i/N).
pi+=((f((double)i/N)+f(((double)i+1)/N))/(2*N));
Related
I am new to C++ and trying to make a program to calculate bond price, the original code works well but I have difficulties transferring it to OOP. mode. The program uses two arrays and a integer to do calculation. I used a loop in constructor to initialize data members (learned from stack over flow). it looks fine but I experienced one error like: no matching function for call to member function. the data can't be passed to member function. I was trapped here a whole day. Could anybody give me some insights? Thank you. The code follows:
#include <array>
#ifndef DRAFT_H
#define DRAFT_H
class Draft
{
public:
Draft(int, double [], double[]);
double F (double);
void Bcalculator (int, double[], double[]);
void printResult();
void printDfactor();
private:
double discF[3]{};
double bPrice {0};
double bDuration {0};
double bConvexity {0};
double term[3];
double cFlow[3];
int sizeofArray;
private:
};
#endif // DRAFT_H
#include "Draft.h"
#include <iostream>
#include <cmath>
#include <array>
#include <iomanip>
using namespace std;
Draft::Draft( int arraySize, double termArr[], double cFlowArr[]):sizeofArray{arraySize}{
for (int i = 0; i < 3; i++){
term[i] = termArr[i];
cFlow[i] = cFlowArr[i];}
}
double Draft::F (double x){
return 0.05 / (1 + exp(-pow((1 + x),2)));
}
void Draft::Bcalculator(int sizeofArray, double term[], double cFlow[]){
double a = 0;
int n = 16;
for (int k =0; k < sizeofArray; k++){
double h = (term[k] - a)/n;
double x[n], fx[n];
for (int i = 0; i <= n; i++){
x[i] = a + i * h;
fx[i] = F(x[i]);
}
double result = 0;
double discF[]{};
for (int i = 0; i <= n; i ++){
if (i == 0 || i == n){
result += fx[i];
}
else if (i % 2 != 0){
result += 4 * fx[i];
}
else {
result += 2 * fx[i];
}
}
result = result * (h/3);
discF[k] = exp (- result);
bPrice += discF[k] * cFlow[k];
bDuration += term[k] * cFlow[k] * discF[k];
bConvexity += pow(term[k], 2) * cFlow[k] * discF[k];
}
bDuration = bDuration / bPrice;
bConvexity = bConvexity / bPrice;
}
void Draft::printDfactor(){
for (int k = 0; k < sizeofArray; k++) {
cout << k + 1 << setw (20) << discF[k] << endl;
}
}
void Draft::printResult()
{
cout << "Bond Price = " << setw(20) << bPrice << endl;
cout << "Bond duration = " <<setw(20) << bDuration <<endl;
cout << "Bond Convexity = " << setw(20) << bConvexity << "\n";
}
#include "Draft.h"
#include <iostream>
#include <cmath>
#include <array>
#include <iomanip>
using namespace std;
int main (){
double termArray[3]{1, 2, 3};
double cFlowArray[3]{5, 5, 105};
int arraySize = 3;
Draft bond1 (arraySize, termArray, cFlowArray);
Draft::Bcalculator();
bond1.printResult();
bond1.printDfactor();
return 0;
}
The error is:
main.cpp|20|error: no matching function for call to
'Draft::Bcalculator include\Draft.h|18|note: candidate: 'void
Draft::Bcalculator(int, double*, double*)'| include\Draft.h|18|note:
candidate expects 3 arguments, 0 provided|
There are two problems in your code.
Definition does not match call. You defined Bcalculator as:
void Draft::Bcalculator(int sizeofArray, double term[], double cFlow[])
But then you call it without arguments:
Draft::Bcalculator();
To be able to call Draft::Bcalculator() you need to add static in the definition:
static void Draft::Bcalculator(int sizeofArray, double term[], double cFlow[])
If you do not want to make it static, call it the normal way, i.e. Draft d{...}; d.Bcalculator().
EDITED
I realized that Bcalculator is using the same three parameters you use to construct and store in Draft class. Therefore, you should call Bcalculator without any arguments and use the class members termArray, cFlowArray and arraySize:
int main ()
{
double termArray[3]{1, 2, 3};
double cFlowArray[3]{5, 5, 105};
int arraySize = 3;
Draft bond1 (arraySize, termArray, cFlowArray);
bond1.Bcalculator();
bond1.printResult();
bond1.printDfactor();
return 0;
}
Then, your definition and implementation of this function has to be changed accordingly:
class Draft
{
public:
...
void Bcalculator(); // <- remove parameters in this definition
private:
double term[3];
double cFlow[3];
int sizeofArray;
}
void Draft::Bcalculator() // <- remove parameters in this implementation
{
... // use automatically the private members term, cFlow and sizeofArray
}
This code works, I compiled it.
Regards!
I'm trying to write a very simple C++ program which outputs a lookup table with the corresponding x and y values of sinus function. The code that I wrote is the following:
#include "stdafx.h"
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
double hw = 4.0;
int nsteps = 30;
const double PI = 3.14159;
const double maxx = hw * PI;
const double deltax = maxx / nsteps;
double x = 0.0;
for (int i = 0; i < nsteps; i++) {
const double f = sin(x);
cerr << x << "\t" << f << endl;
x = x + deltax;
}
return 0;
}
Now the program is working, but my problem is, that the values are not getting aligned properly as showed in the following picture
So is there any way, to achieve that the second column of the values will actually be a column and all the values are aligned at the same position? What could I use instead of \t?
The above answer provides an incorrect solution because the alignment is not set correctly. I would use a function to handle the formatting:
#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
void printxy(double x, double y, int width){
cout << setw(width) << x << "\t";
if (y < 0) cout << "\b";
cout << setw(width) << y << "\n";
}
int main(){
double hw = 4.0;
int nsteps = 30;
const double PI = 3.14159;
const double maxx = hw * PI;
const double deltax = maxx / nsteps;
double x = 0.0;
int decimals = 6;
int width = 8; //Adjust as needed for large numbers/many decimals
cout << std::setprecision(decimals);
cout << std::setw(width);
cout.setf(ios::left);
for (int i = 0; i < nsteps; i++) {
const double y = sin(x);
printxy(x, y, width);
x = x + deltax;
}
}
The output is now formatted correctly:
0 0
0.418879 0.406736
0.837757 0.743144
1.25664 0.951056
1.67551 0.994522
2.09439 0.866026
2.51327 0.587787
2.93215 0.207914
3.35103 -0.207909
3.76991 -0.587783
4.18879 -0.866024
4.60767 -0.994521
5.02654 -0.951058
5.44542 -0.743148
5.8643 -0.406741
6.28318 -5.30718e-06
6.70206 0.406731
7.12094 0.743141
7.53982 0.951055
7.95869 0.994523
8.37757 0.866029
8.79645 0.587791
9.21533 0.207919
9.63421 -0.207904
10.0531 -0.587778
10.472 -0.866021
10.8908 -0.994521
11.3097 -0.951059
11.7286 -0.743151
12.1475 -0.406746
I would also discourage the use of cerr for these kinds of printing operations. It is intended for printing errors. Use cout instead (it works the same way for all practical purposes).
I should also mention that endl is a ticking bomb: it flushes the output, meaning that the internal buffer of the stream is written out (be it the console, a file or whatever). When applications scale and become more IO intensive, this can become a significant performance problem: the buffer that is intended to increase the IO performance is potentially unused due to frequent endl insertions. The solution is to use the newline character '\n'.
Use std::setprecision() to set count number for decimal after point, and std::setw() to set width of output length. Include <iomanip> needed, example:
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
int main()
{
double hw = 4.0;
int nsteps = 30;
const double PI = 3.14159;
const double maxx = hw * PI;
const double deltax = maxx / nsteps;
double x = 0.0;
cerr << std::setprecision(8);
for (int i = 0; i < nsteps; i++) {
const double f = sin(x);
cerr << std::setw(20) << x << std::setw(20) << f << endl;
x = x + deltax;
}
return 0;
}
Output is:
0 0
0.41887867 0.40673632
0.83775733 0.74314435
1.256636 0.95105619
1.6755147 0.99452204
2.0943933 0.86602629
2.513272 0.58778697
2.9321507 0.20791411
3.3510293 -0.20790892
3.769908 -0.58778268
4.1887867 -0.86602363
//...
I made a GBM function in C++ and I believe I am getting too much of a range of stock prices when I start with an initial price of 100 the output can be from [50,400]. I am not sure what I am doing wrong in my code, I am guessing there is something wrong with the way I seed the random standard normal numbers. Please have a look at the function and let me know if there is anything I shold modify or change.
Here is the function:
std::vector<double> GBM(const int M, const int N, const double T, const double r, const double q, const double sigma, const double S0){
double dt = T/N;
std::vector<double> Z;
std::vector<double> S;
S.push_back(S0);
std::mt19937 e2(time(0));
std::normal_distribution<double> dist(0.0, 1.0);
for(int i = 0; i < M; i++){
Z.push_back(dist(e2));
}
double drift = exp(dt*((r - q)-0.5*sigma*sigma));
double vol = sqrt(sigma*sigma*dt);
for(int i = 1; i < M; i++){
S.push_back(S[i-1] * drift * exp(vol*Z[i]));
}
return S;
}
Here is the main.cpp file that utilizes the function above:
#include <iostream>
#include "LSM.h"
#include <cmath>
#include <ctime>
#include <Eigen/Core>
#include <Eigen/SVD>
#include <iostream>
#include <vector>
#include <random>
std::vector<double> GBM(const int M, const int N, const double T, const double r, const double q, const double sigma, const double S0);
int main(){
const double r = 0.04; // Riskless interest rate
const double q = 0.0; // Divident yield
const double sigma = 0.20; // Volatility of stock
const double T = 1; // Time (expiry)
const int N = 1000; // Number of time steps
const double K = 100.0; // Strike price
const double S0 = 100.0; // Initial stock price
const int M = 10000; // Number of paths
const int R = 2; // Choice of basis for Laguerre polynomial
//LSM Option_value(r,q,sigma,T,N,K,S0,M,R);
std::vector<double> s = GBM(M,N,T,r,q,sigma,S0);
for(int i = 0; i < M; i++){
std::cout << s[i] << std::endl;
}
return 0;
}
A typical output that one should get starting with an initial stock price of 100 is below:
153.5093
132.0190
96.2550
106.5196
58.8447
135.3935
107.1194
101.2022
134.2812
82.2146
87.9162
74.9333
88.9137
207.5150
123.7893
95.8526
120.0831
96.3990
103.3806
113.8258
100.6409
92.0724
81.1704
121.9925
114.3798
117.8366
86.1070
74.4885
82.6013
78.0202
97.0586
119.7626
89.0520
72.2328
92.1998
84.7180
138.9160
91.0091
105.2096
91.3323
79.0289
115.9377
75.4887
123.2049
101.1904
95.9454
82.4181
108.8314
123.0198
76.8494
94.8827
149.5911
95.6969
143.3498
87.0939
77.3033
105.8185
122.3455
79.8208
112.9913
120.1649
131.3052
136.8246
96.5455
109.0187
87.1363
103.1835
106.3896
143.9496
119.1357
99.9114
111.1409
79.0563
147.1506
105.7851
99.7089
117.8770
99.7602
73.1796
125.8698
109.4367
135.5020
88.1979
129.8502
121.1233
76.7520
86.5296
118.6721
83.2511
116.3950
99.8795
70.6895
64.9578
111.4750
102.6343
82.8765
90.3479
106.8873
106.3850
119.3399
Function GBM should simulate 1 path every time. So no need to supply M. And the path length is, in your code, defined by N instead of M.
If you implement this change, GBM return the whole simulated path.
Then you need to call GBM M times in order to calculate all the simulations.
Also there is no need to store all the random numbers generated.
Based on your sample, something like this:
#include <iostream>
#include <vector>
#include <random>
// Random generator initialize (only once).
static std::mt19937 rng(time(0));
std::vector<double> GBM(const int N, const double T, const double r,
const double q, const double sigma, const double S0)
{
double dt = T/N;
std::vector<double> S;
S.push_back(S0);
std::normal_distribution<double> dist(0.0, 1.0);
double drift = exp(dt*((r - q)-0.5*sigma*sigma));
double vol = sqrt(sigma*sigma*dt);
for(int i = 1; i < N; i++){
double Z = dist(rng);
S.push_back(S[i-1] * drift * exp(vol*Z));
}
return S;
}
int main(){
const double r = 0.04; // Riskless interest rate
const double q = 0.0; // Divident yield
const double sigma = 0.20; // Volatility of stock
const double T = 1; // Time (expiry)
const int N = 1000; // Number of time steps
const double S0 = 100.0; // Initial stock price
const int M = 100; // Number of paths
for (int sindx = 0; sindx < M; sindx++)
{
std::vector<double> s = GBM(N,T,r,q,sigma,S0);
std::cout << "Simulation " << sindx << ": "
<< s[0] << ", " << s[1] << " ... " << s[N-2] << ", " << s[N-1]
<< std::endl;
}
return 0;
}
From the comments behind the constants, you want to simulate 10000 paths of an integration from 0 to 1 using 1000 subdivision steps, i.e., a step size of 0.001.
What you are doing is integrating one path over 10000 steps of step size 0.001, that is, from 0 to 10.
If you do this correctly, the result should look like a list of
S0 * exp( ((r-q)-0.5*sigma*sigma)*T + sigma*sqrt(T)*Z[i] )
as the value of the GBM at time T only depends on W(T) which is distributed as N(0,T) or sqrt(T)*N(0,1).
I wanted to find out the machine epsilon for float and double types through C++, but I am getting the same answer again and again for each data type of variable x I am using, which is that of long double and of the order of O(1e-20). I am running it on my Windows 10 machine using Codeblocks.
I tried using the same code in Ubuntu and also in DevC++ in Windows itself, I am getting the correct answer. What is it that I am doing wrong in codeblocks. Is there any default setting?
#include <iostream>
#include <string>
#include <typeinfo>
using namespace std;
int main()
{
//double x = 5;
//double one = 1;
//double fac = 0.5;
float x=1;
float one = 1.0;
float fac = 0.5;
// cout <<"What is the input of number you are giving"<< endl;
// cin >> x;
cout <<"The no. you have given is: "<< x << endl;
int iter = 1;
while(one+x != one)
{
x = x * fac;
iter = iter + 1;
}
cout<<"The value of machine epsilon for the given data type is "<<x<<endl;
cout<<"The no.of iterations taken place are: "<<iter<<endl;
}
while(one+x != one)
The computation of one+x might well be an extended precision double. The compiler is quite free to do so. In such an implementation, you will indeed see the same value for iter regardless of the type of one and x.
The following works quite nicely on my computer.
#include <iostream>
#include <limits>
template <typename T> void machine_epsilon()
{
T one = 1.0;
T eps = 1.0;
T fac = 0.5;
int iter = 0;
T one_plus_eps = one + eps;
while (one_plus_eps != one)
{
++iter;
eps *= fac;
one_plus_eps = one + eps;
}
--iter;
eps /= fac;
std::cout << iter << ' '
<< eps << ' '
<< std::numeric_limits<T>::epsilon() << '\n';
}
int main ()
{
machine_epsilon<float>();
machine_epsilon<double>();
machine_epsilon<long double>();
}
You could try this code to obtain the machine epsilon for float values:
#include<iostream>
#include<limits>
int main(){
std::cout << "machine epsilon (float): "
<< std::numeric_limits<float>::epsilon() << std::endl;
}
I've written a few programs to find pi, this one being the most advanced. I used Machin's formula, pi/4 = 4(arc-tan(1/5)) - (arc-tan(1/239)).
The problem is that however many iterations I do, I get the same result, and I can't seem to understand why.
#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;
double arctan_series(int x, double y) // x is the # of iterations while y is the number
{
double pi = y;
double temp_Pi;
for (int i = 1, j = 3; i < x; i++, j += 2)
{
temp_Pi = pow(y, j) / j; //the actual value of the iteration
if (i % 2 != 0) // for every odd iteration that subtracts
{
pi -= temp_Pi;
}
else // for every even iteration that adds
{
pi += temp_Pi;
}
}
pi = pi * 4;
return pi;
}
double calculations(int x) // x is the # of iterations
{
double value_1, value_2, answer;
value_1 = arctan_series(x, 0.2);
value_2 = arctan_series(x, 1.0 / 239.0);
answer = (4 * value_1) - (value_2);
return answer;
}
int main()
{
double pi;
int iteration_num;
cout << "Enter the number of iterations: ";
cin >> iteration_num;
pi = calculations(iteration_num);
cout << "Pi has the value of: " << setprecision(100) << fixed << pi << endl;
return 0;
}
I have not been able to reproduce your issue, but here is a bit cleaned up code with a few C++11 idioms and better variable names.
#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;
// double arctan_series(int x, double y) // x is the # of iterations while y is the number
// then why not name the parameters accoringly? In math we usually use x for the parameter.
// prefer C++11 and the auto notation wherever possible
auto arctan_series(int iterations, double x) -> double
{
// note, that we don't need any temporaries here.
// note, that this loop will never run, when iterations = 1
// is that really what was intended?
for (int i = 1, j = 3; i < iterations; i++, j += 2)
{
// declare variables as late as possible and always initialize them
auto t = pow(x, j) / j;
// in such simple cases I prefer ?: over if-else. Your milage may vary
x += (i % 2 != 0) ? -t : t;
}
return x * 4;
}
// double calculations(int x) // x is the # of iterations
// then why not name the parameter accordingly
// BTW rename the function to what it is supposed to do
auto approximate_pi(int iterations) -> double
{
// we don't need all of these temporaries. Just write one expression.
return 4 * arctan_series(iterations, 0.2) - arctan_series(iterations, 1.0 / 239.0);
}
auto main(int, char**) -> int
{
cout << "Enter the number of iterations: ";
// in C++ you should declare variables as late as possible
// and always initialize them.
int iteration_num = 0;
cin >> iteration_num;
cout << "Pi has the value of: "
<< setprecision(100) << fixed
<< approximate_pi(iteration_num) << endl;
return 0;
}
When you remove my explanatory comments, you'll see, that the resulting code is a lot more concise, easier to read, and therefore easier to maintain.
I tried a bit:
Enter the number of iterations: 3
Pi has the value of: 3.1416210293250346197169164952356368303298950195312500000000000000000000000000000000000000000000000000
Enter the number of iterations: 2
Pi has the value of: 3.1405970293260603298790556436870247125625610351562500000000000000000000000000000000000000000000000000
Enter the number of iterations: 7
Pi has the value of: 3.1415926536235549981768144789384678006172180175781250000000000000000000000000000000000000000000000000
Enter the number of iterations: 42
Pi has the value of: 3.1415926535897940041763831686694175004959106445312500000000000000000000000000000000000000000000000000
As you see, I obviously get different results for different numbers of iterations.
That method converges very quickly. You'll get more accuracy if you start with the smallest numbers first. Since 5^23 > 2^53 (the number of bits in the mantissa of a double), probably the maximum number of iterations is 12 (13 won't make any difference). You'll get more accuracy starting with the smaller numbers. The changed lines have comments:
double arctan_series(int x, double y)
{
double pi = y;
double temp_Pi;
for (int i = 1, j = x*2-1; i < x; i++, j -= 2) // changed this line
{
temp_Pi = pow(y, j) / j;
if ((j & 2) != 0) // changed this line
{
pi -= temp_Pi;
}
else
{
pi += temp_Pi;
}
}
pi = pi * 4;
return pi;
}
For doubles, there is no point in setting precision > 18.
If you want an alternative formula that takes more iterations to converge, use pi/4 = arc-tan(1/2) + arc-tan(1/3), which will take about 24 iterations.
This is another way if some of you are interested. The loop calculates the integral of the function : sqrt(1-x²)
Which represents a semicircle of radius 1. Then we multiply by two the area. Finally we got the surface of the circle which is PI.
#include <iomanip>
#include <cmath>
#define f(x) sqrt(1-pow(x,2))
double integral(int a, int b, int p)
{
double d=pow(10, -p), s=0;
for (double x=a ; x+d<=b ; x+=d)
{
s+=f(x)+f(x+d);
}
s*=d/2.0;
return s;
}
int main()
{
cout << "PI=" << setprecision (9) << 2.0*integral(-1,1,6) << endl;
}