pi

closed account (4wpL6Up4)
Hi,

I am writing a program that has to calculate pi with montecarlo method.
The arrow should hit the points x and y,and they should both be globally defined this way:

struct Coord
{
double x, y;
};


a function must be written which returns a coordinate of the type Coord. The throws are
done by generating random numbers for x and y within the square area. The random
coordinate is returned in a structure of the type Coord.
Another function (boolean) should take which takes a coordinate of the type Coord as argument and returns true if the coordinate falls below the circle arc.
another function shall take an integer n as an argument,
throw an arrow n times and then print the n-value, the Pi value with 5 decimals calculated
with the formula written in the code below, as well as the relative fault with 1 decimal.


The code I have written does not give me an outcome that makes much sense, especially the last function. Moreover, I am having difficulties in dealing with "Struct coord", in fact, as you can see, I wrote x and y directly instead.

Any hint about how to solve this issues would be appreciated.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  #include "pch.h"
#include <stdlib.h>
#include<iostream>
#include<cstdlib>
#include<cctype>
#include <sstream>
#include <string>
#include<cmath>
#include <algorithm>
#include <iterator>
#include <ctype.h>
#include <iomanip>
#include <limits>
#include<cstdlib>



using namespace std;

void throww(double &x, double &y);
bool below(double &x, double &y, double &dist);
void throwseries(double &x, double &y, int &n, double &dist);
const double R = 1;
const double pi = 3.14159265359;

int main()
{
	int n;
	//struct coord
	//{
	double x, y, dist;
	//};

	char answer;
	do {
		throww(x, y);
		below(x, y, dist);
		throwseries(x, y, n, dist);


		cout << "try again(Y/N)?";
		cin >> answer;
		cin.ignore();
	} while (answer == 'Y' || answer == 'y');

	return 0;
}

void throww(double &x, double &y)
{
	int m;
	cout << "Please enter the seed number." << endl;
	cin >> m;
	for (int i = 0; i <= m; i++) {
		x = (double)rand() / (double)RAND_MAX;
		y = (double)rand() / (double)RAND_MAX;
	}
	double dist = sqrt(x*x) + sqrt(y*y);
	cout << dist << endl;
}

bool below(double &x, double &y, double &dist)
{
	if (dist <= R)
		return true;
	else
		return false;
}

void throwseries(double &x, double &y, int &n, double &dist)
{

	double relfault, calcpi;
	long long int in_circle = 0;
	long long int out_circle = 0;
	calcpi = double(in_circle) / double(out_circle) * 4;
	relfault = ((calcpi - pi) / pi)*100.0;
	cout << "enter n" << endl;
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		if (dist = true)
			in_circle++;
		out_circle++;
	}
	cout << calcpi << setw(5) << endl;
	cout << relfault << setw(1) << endl;
}
Last edited on
code executes sequentially from top to bottom
74
75
76
	long long int in_circle = 0;
	long long int out_circle = 0;
	calcpi = double(in_circle) / double(out_circle) * 4;
¿how much is 0/0*4?

functions communicate throught their parameters and return value
a local variable defined inside a function is only relevant inside that function, you can't see it outside that function.
two variables defined in two different functions have no relationship whatever their name is, it does not matter that their name is the sam.
`dist' in `main()' is uninitialised.
`dist' in `throww()' exists only there
`dist' in `below()' is the one from main() passed as a parameter (uninitialised)
`dist' in `throwseries()' is the one from main() passed as a parameter (uninitialised)


the only parameter of `throwseries()' should be `n'.
you don't intend to modify it, so it makes no sense to pass it by reference
1
2
3
4
5
6
7
8
//pseudocode
define throwseries(n):
   in_circle = 0
   repeat(n):
      x, y = throw()
      if below(x, y):
         in_circle += 1
   return in_circle/n
closed account (4wpL6Up4)
now is confusing.
I have initialized and added parameters but I get an error message on line 62 (C2082).
In addition, x and y should be globally declared this way
struct Coord
{
double x, y;
};
but I am not sure how to use them after such a declaration.
Here is my new code but it does not run due to the issues I just wrote.
Maybe I misunderstood you.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
struct Coord 
#include "pch.h"
#include <stdlib.h>
#include<iostream>
#include<cstdlib>
#include<cctype>
#include <sstream>
#include <string>
#include<cmath>
#include <algorithm>
#include <iterator>
#include <ctype.h>
#include <iomanip>
#include <limits>
#include<cstdlib>



using namespace std;

void throww(double &x, double &y, double &dist);
bool below(double &x, double &y, double &dist);
void throwseries(double &x, double &y, int &n, double &dist);
const double R = 1;
const double pi = 3.14159265359;

int main()
{
	int n;
	double dist = 0;

	//struct coord
	//{
	double x=0, y=0;
	//};
	char answer;
	do {
		throww(x, y, dist);
		below(x, y, dist);
		throwseries(x, y, n, dist);


		cout << "try again(Y/N)?";
		cin >> answer;
		cin.ignore();
	} while (answer == 'Y' || answer == 'y');

	return 0;
}

void throww(double &x, double &y, double &dist)
{
	int m;
	cout << "Please enter the seed number." << endl;
	cin >> m;
	for (int i = 0; i <= m; i++) {
		x = (double)rand() / (double)RAND_MAX;
		y = (double)rand() / (double)RAND_MAX;
	}
	
	double dist = sqrt(x*x) + sqrt(y*y);
	cout << dist << endl;
}

bool below(double &x, double &y, double &dist)
{
	if (dist <= R)
		return true;
	else
		return false;
}

void throwseries(double &x, double &y, int &n, double &dist)
{

	double relfault, calcpi;
	long long int in_circle =0;
	long long int out_circle =0;
	calcpi = double(in_circle) / double(out_circle) * 4;
	relfault = ((calcpi - pi) / pi)*100.0;
	cout << "enter n" << endl;
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		if (dist = true)
			in_circle++;
		out_circle++;
	}
	cout << calcpi << setw(5) << endl;
	cout << relfault << setw(1) << endl;
}
double dist = sqrt(x*x) + sqrt(y*y);

This means "create a NEW double, called dist".


Take a look at the function it's in:
1
2
3
4
5
6
7
8
9
10
11
12
13
void throww(double &x, double &y, double &dist)
{
	int m;
	cout << "Please enter the seed number." << endl;
	cin >> m;
	for (int i = 0; i <= m; i++) {
		x = (double)rand() / (double)RAND_MAX;
		y = (double)rand() / (double)RAND_MAX;
	}
	
	double dist = sqrt(x*x) + sqrt(y*y);
	cout << dist << endl;
}


The function ALREADY has a variable named dist, passed in as a parameter. So why are you trying to create a whole new variable named dist?
closed account (4wpL6Up4)
Thanks!
How to include x and y
once they are declared this way?

struct Coord
{
double x, y;
};
Last edited on
1
2
3
4
5
6
7
8
Coord throww(); //notice that it takes no parameter
bool below(Coord p); //here should be the distance computation
void throwseries(int n){
   //...
   Coord p = throww();
   if(below(p))
      //...
}



¿did you understand the pseudocode?
Hi nypren!

in your code line 58 is double dist = sqrt(x*x) + sqrt(y*y); what could be simplified to dist = x + y;
I assume, x and y are coordinates within a orthogonal system, in that case the distance of point (x, y) to the origin would be dist = sqrt(x*x + y*y); due to Pythagoras.

I myself am new to C++, since two weeks I have VS2010 installed and compiled with success a simple modifcation of an existing program. I made my living with other languages. So I may not answer your question about
struct Coord
{
double x, y;
};

But an advice, keep it simple and smart. Less code enhances the readability, reduces the chance for typ0s, and gives you more time for comments (which could be of some help in future). Reading along the tutorial of this site, I took the "Pi by Mote Carlo" as an exercise for myself. Here my suggestion (which confirms the saying, a good FORTRAN programmer may do FORTRAN in any language):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/* PiRan: Compute Pi using Monte Carlo Method */
#include <iostream>
using namespace std;

void main()
{
	unsigned long n, t, hit(0), x, y, Rsqr=RAND_MAX*RAND_MAX;
	char a;
once_more:
	cout << "Please enter numbers of throws: "; cin >> n;

	t = n;		/* keep for later use */
	while (n-->0) {
		x = rand(); y = rand();
		hit += x*x+y*y < Rsqr ? 1 : 0;
	}

	cout << "Pi is approximately " << 4.0 * hit / t << endl;

ask_again:
	cout << "Try it again(Y/N)? ";
	cin >> a;
	if (a == 'Y' || a == 'y') goto once_more;
//	if (a != 'N' && a != 'n') goto ask_again;
}

The main structure is input data - compute - output result. The jump back to do it once more is already a concession to the pretentious target group. (The jump to label ask_again: gives the chance for an endless loop as I do not yet fully understand cin.)
In the repeating loop I kept only the necessary, I even compare the squared values to avoid time consuming square root and avoid the need of real variables, approximating transcendental Pi by inters only.

Your task to use
struct Coord { double x, y; };
looks like object oriented programming, where you have a Point which may tell you his Coordinates, and if it's a good Point it may even tell you the distance to the origin (if the programmer new the correct formula). Those concepts are not new but still a cultural clash for me.

Please let us know how your solved the task using
struct Coord { double x, y; };
By making it user friendly I forgot to reset the hit count. Insert hit=0; after the label once_more:
I think an initial call to srand() is in order.

And it's int main(), not void main().

And RAND_MAX*RAND_MAX overflows a 4-byte integer in many implementations (including cpp.sh).

And if you are using goto in Fortran then you are 50 years out of date.
Last edited on
Thank you for taking a look at my code.

I think an initial call to srand() is in order.

Understood, I found in the reference part of this site the suggestion srand (time(NULL)); -- it works albeit the compiler shows warnings.

And it's int main(), not void main().

Thank you, I've overlooked the the "implicit return 0; statement for main" in the tutorial.

And RAND_MAX*RAND_MAX overflows a 4-byte integer in many implementations (including cpp.sh).

Just found on cpp.sh that unsigned long long does not cure this problem. As I do not want to give up the compare of squared distance vs squared radius, I have to take the reminder of rand() that fits in a 4-byte integer. But... then I have to test if rand()%FFFF is still as random as rand() on its own.

And if you are using goto in Fortran then you are 50 years out of date.

50 years? Darn! How time flies... In 1969 FORTRAN-66 was still in use, the specification of FORTRAN-77 was released 1978, please tell me what replaced GOTO. Why does it still exist in more recent languages like C++?
Here how I prevent overflow of square(rand()), instead of rand() I use rand() modulo sqrt(machine max).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/* PiRan: Compute Pi using Monte Carlo Method */
#include <stdlib.h>     /* srand, rand */
#include <time.h>       /* time */
#include <iostream>	/* cout, cin, endl */
using namespace std;

int main()
{
	unsigned long n, t, hit(0), x, y, R, c(0), h(0);
	char a;

/* first get square root of machine max value */
    h -= 1;		/* machine max, works only with unsigned integer types */
    do {} while (c+=1, h/=2, h!=0);
    h = 1;		/* init next loop */
    c /= 2;		/* half exponent = sqare root */
    do {h += h;} while (--c != 0);

/* full stop if RAND_MAX is exact multiple of sqrt(machine max) or too little */
	if (RAND_MAX % h < 100)
	{
		cout << "Algorithm fails on this machine.";
		exit (EXIT_FAILURE);
	}

/* get the square of the circle's radius */
	R = RAND_MAX % h;	/* prevent overflow of R*R */
	R *= R;
	srand (time(NULL));
once_more:
	cout << "Please enter numbers of throws: "; cin >> n;

/* count the result for n trials */
	t = n;		/* keep for later use */
	while (n-->0) {
		x = rand() % h; y = rand() % h;
		hit += x*x+y*y < R ? 1 : 0;
	}

/* Present the result */
	cout << "Pi is approximately " << 4. * hit / t << endl;
	hit = 0;

// ask_again:
	cout << "Try it again(Y/N)? ";
	cin >> a;
	if (a == 'Y' || a == 'y')
		goto once_more;
//	if (a != 'N' && a != 'n') goto ask_again;  /* gives the chance of endless loop */
}


Edit: Had to remove comment in line 37, the shown formula
/* hit += x*x+y*y / R should work too (integer arithmetic), alas it does not, so... */
counts the hits outside the circle.
Last edited on
Just in case someone wondered already weeks ago, today I found an error in a comment and removed it -- http://www.cplusplus.com/forum/beginner/250481/#msg1103341
Topic archived. No new replies allowed.