Can you find an error here?

Hi! Me again ( .)‿( .)
Hopefully it's something more interesting this time.
So I want to write the program that computes a delicious Pie via this "random" number generation.

The math behind this is as follows:

-We have a circle with radius 1.

-That circle is drawn inside a square with sides 2x2.

-Imagine you throw darts at that construction.

-If you throw enough darts [n] at the construction then
[n - total darts thrown]/[in - darts inside the circle] = [4 - area of the square]/[a - area of the circle]

-From that we can calculate our dessert using π=a/r2

-Since r=1 and area of the square is 4, we can simply find 1 quadrant, it would be easier.

-The formula then is just 4*[a/4]/r2, i.e. ([in/n]*4)

-[a/4] is [in - darts inside the circle]/[n - total darts thrown]

- We can check if the darts are in the circle using d2=x2+y2, where x and y are randomly generated coordinates of the dart.

The code I created is this:
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
#include <iostream>
#include <Windows.h>
#include <cmath>
#include <stdlib.h>
#include <ctime>

using namespace std;

double Pie ()
{
	srand(time(0)); //initiate the seed
	int n=0;
	cout << "How many darts ye wanna throw? \n";
	cin >> n;
	int in = 0; //set variable for darts inside the circle
	if (n<0) {cout << "FAKer! Ye can't throw negative darts, they won't stick! \n"; return NULL;} //Politely inform the user that they have entered a wrong value.
	else
	{
		for (int i= 0; i<n; i++)
		{
			double x = rand() / RAND_MAX; //Initiate random variables for coordinates of the dart between 0 and 1
			double y = rand() / RAND_MAX;
			if (sqrt(x*x + y*y) < 1) in++; // Check if the distance to origin is less than radius and add correct darts to the [in]
		}
	}
	return (in/static_cast<double>(n)*4); //[a/4] is [in/n] so pi=[in/n]*4
}

int main () //Print that crap
{
double t = Pie();
t != 0 ? cout << t : cout << "Error";
Sleep(5000);
return 0;
}


However it does not give value close to Pi even if I enter some 5 million or something. It gives a value close to 4 instead. I am struggling with finding a mistake in the code, maybe someone can help?

Please ignore the lousy error catching. I don't know how to do that properly yet and I also deliberately use methods I have just learned so I remember them better.

PS: These forums really need a [list][/list] functionality.
Last edited on
rand() returns an integer type. RAND_MAX will be an integer type.
When you divide an integer type by an integer type in C++, the result is an integer type.

Try changing line 21 to double x = static_cast<double>(rand()) / RAND_MAX; and making a corresponding change to line 22.
Oh that's brilliant! That did it! I am very new to all the data types stuff, I very often mess up with them. When there are so many I certainly miss something.

So essentially rand will work with double if you convert? It's a bit strange to me because I thought if it creates an integer, then if you convert it would still be an integer, only with .0 in the end. E.g. 5-->5.0
So that's apparently not how it is?

Anyway thanks for the help that was fast!
Last edited on
So essentially rand will work with double if you convert? It's a bit strange to me because I thought if it creates an integer, then if you convert it would still be an integer, only with .0 in the end. E.g. 5-->5.0
So that's apparently not how it is?


I think you're a little confused. Integer types don't have decimal portions, whether they are 0 or something else. So, when you divide an integer type by an integer type, the resulting value is an integer type. However, when one of the operands is a floating point type (like double) the other operand will be promoted to the same type and the result will be a floating point type.

1
2
3
4
5
6
7
#include <iostream>

int main()
{
    std::cout << "5 / 2   = " << 5/2 << '\n' ;
    std::cout << "5.0 / 2 = " << 5.0/2 << '\n' ;
}
5 / 2   = 2
5.0 / 2 = 2.5
Yeah "confused" LOL. More like brain melted.

I see now. So is the left side operand always the "dominant" one and the right one gets promoted? Or is it a hierarchy between types (like int/double will still yield double)?

This whole data type thing is really giving me a migraine, this and using pointers are the most cumbersome things to learn in C++ :P

And why do you (as you, people on this forum) always use the std:: thing instead of telling the program that you use std namespace? I have read that the recommended practice is to say "using namespace std" since it's cleaner. Was it wrong? I have 2 books on C++ and they contradict with each other a lot, it's a pain in the @55.
Last edited on
I see now. So is the left side operand always the "dominant" one and the right one gets promoted? Or is it a hierarchy between types (like int/double will still yield double)?

http://stackoverflow.com/questions/5563000/implicit-type-conversion-rules-in-c-operators

I have read that the recommended practice is to say "using namespace std" since it's cleaner.

The practice is never recommended by anyone with any experience, as it greatly increases the chances of name clashes between your identifiers and those used in the std namespace. That's not to say you should never have a using directive, but it should be very rare to see the entire std namespace brought into the global namespace on a serious project. Books typically use a using directive (either explicitly or implicitly) in examples in order to make code examples more readable in the limited space available. They generally have some sort of disclaimer somewhere that this is what they're doing (often in the foreword or introduction.)

The above program could be rewritten like so:

1
2
3
4
5
6
7
8
#include <iostream>

int main()
{
    using std::cout ;
    cout << "5 / 2   = " << 5/2 << '\n' ;
    cout << "5.0 / 2 = " << 5.0/2 << '\n' ;
}


which limits the scope of the using directive to main so that it doesn't affect other code in the same translation unit, and only brings a very narrow slice of the std namespace into the global one.
Ok I will keep that in mind. The place where i read that it was best to type the namespace in global scope was the lecture nots from MIT open course:
http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-096-introduction-to-c-january-iap-2011/lecture-notes/MIT6_096IAP11_lec01.pdf

Thanks for clearing this confusion up for me.
Topic archived. No new replies allowed.