问题
I am trying to calculate PI using Monte Carlo method. My code gives the result 3.000 no matter how big MAXLEN is. After debugging it many times, I couldn't get what I'm doing wrong.
#include <stdio.h>
#include <stdlib.h>
#define sqr2(x) ((x)*(x))
#define frand() ((double) rand() / (RAND_MAX))
#define MAXLEN 1000
int circumscribed(int radius){
float xcoord = frand();
float ycoord = frand();
float coord = sqr2(xcoord) + sqr2(ycoord);
if(coord <= radius)
return 1;
return -1;
}
int main()
{
int i;
int circles = 0, rect = 0;;
for(i = 0; i < MAXLEN; i++)
{
if(circumscribed(1) > 0) // if(circumscribed(1)) shoul be enough but it doesn't work. Very odd in my opinion.
circles++;
rect++; //this is equal to MAXLEN, I just used it for debugging
}
float PI = 4 * circles / rect;
printf("PI is %2.4f: \n", PI);
return 0;
}
回答1:
Since circles and rect are both int, the result of 4 * circles / rect will be an int. Use floating point numbers instead.
float PI = 4.0 * (float)circles / rect;
回答2:
This expression is all integers:
4 * circles / rect;
Therefore, the result is an integer (3 in this case).
(as a similar example: 10 / 3 == 3, but 10.0 / 3.0 == 3.333333)
Try instead:
4.0 * circles / rect;
Just changing the (int)4 to a (double)4 by referring to it as 4.0 or even 4. should be enough.
Other Misc Observations
This line has an extra semi-colon:
int circles = 0, rect = 0;;
Your function circumscribed uses float. Your variable PI is also a float.
If you use double, you'll get greater precision.
回答3:
You are doing integer Math here. circles and rect are both int in your code, so the result of 4 * circles / rect is also an int. Use floating point numbers instead. Use double for better precision.
double PI = 4.0 * (double)circles / rect;
回答4:
You are performing integer math here:
float PI = 4 * circles / rect;
Changing 4 to 4.0 is sufficient to fix the problem:
float PI = 4.0 * circles / rect;
Working version here
回答5:
float PI = 4 * circles / rect;
This performs integer math to the right of the = thus limiting your result to 1 significant digit.
Instead:
double PI = 4.0 * circles / rect; // Best
Details
float PI = 4.0 * (float)circles / rect; // OK
Recommend avoid using float. Use double instead to avoid limiting this Monte Carlo to about 7 digits. As circles becomes large, it may not convert exactly into the same float value. Instead it converts into a rounded float. This happens at about circles > 8,000,000 on many machines. By rounding, you are unnecessarily limiting the attainable precision. Using a double, this rounding does not occur until circles is about 9e15.
float PI = 4.0 * (double) circles / rect; // Better
The explicit cast of (double) circles may be useful to the reader, but code will perform the same way with or without it. 4.0 is a double and will cause a double promotion to circles before the multiplicity occurs, even without the cast.
double PI = 4.0 * circles / rect; // Better
As the 4.0 * ... result is a double, best precision is retained by saving to a double. Using float PI causes the multiplication/division, which was done in double precision to reduce its precision on saving to a float.
float or double PI = ...
printf("PI is %2.4f: \n", PI);
Note: Here, a PI converted to a double is passed to printf() regardless if PI was declared float or double. So might as access the precision in PI by declaring it double.
Note: int, float and double range and precision are machine dependent. The above reflects a common implementation.
回答6:
CHECK OUT THIS CODE:
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#define SEED 35791246
int main(int argc, char** argv)
{
int niter=0;
double x,y;
int i,count=0; /* # of points in the 1st quadrant of unit circle */
double z;
double pi;
printf("Enter the number of iterations used to estimate pi: ");
scanf("%d",&niter);
/* initialize random numbers */
srand(SEED);
count=0;
for ( i=0; i<niter; i++) {
x = (double)rand()/RAND_MAX;
y = (double)rand()/RAND_MAX;
z = x*x+y*y;
if (z<=1) count++;
}
pi=(double)count/niter*4;
printf("# of trials= %d , estimate of pi is %g \n",niter,pi);
return 0;
}
来源:https://stackoverflow.com/questions/17659652/calculating-pi-using-monte-carlo-method-gives-imprecise-answer