我试图通过随机数生成器编写一个基于蒙特卡罗方法估计Pi的程序。我试图在1,2,3,4,5和6位精度内估算Pi,并让程序在屏幕上打印到Pi的1位数,然后是Pi的0.01位数。等等,一直到Pi的.000001位数。我允许用户输入他们想要运行的试验数量,因此它将打印“试验1,2,3,4”等,并附上我在上面列出的所有信息。我被困在最后一点,这是让它循环回计算(它不会打印超过试验1)。虽然我没有收到程序已终止的消息,但我无法分辨是否是我的while循环失败或我的嵌套for循环。请帮忙! :)
我试图切换for循环以及尝试不同的if语句。除了允许用户运行多个试验之外,这是我最接近运行的方式。
#include "pch.h"
#include <iostream> //need this by default for cin
#include <math.h> //includes math functions
#include <cmath> //includes basic math
#include <cfloat> //includes floating point numbers
#include <iomanip> //includes setprecision for decimal places
#include <cstdlib> //needed for rand and srand functions
#include <ctime> //needed for time function used to seed generator
using namespace std;
int main()
{
cout << "The purpose of this program is to estimate pi using the monte
carlo method and a random number generator" << endl << endl;
unsigned seed = time(0);
srand(seed);
float radius;
int trialcount = 0;
int trials;
float accuracy;
const float pi = 3.14159265;
float randpi = 0;
int squarecount = 0;
int circlecount = 0;
float x;
float y;
int n;
cout << "The value of PI can be found as the ratio of areas of a circle of radius r located within a square of side 2r" << endl;
cout << "This program runs a MonteCarlo Simulation that generates numbers located randomly within a square" << endl;
cout << "The count of values within the square and the count of numbers within the circle approximate their areas" << endl;
cout << "An input value of radius determines the size of the circle and square" << endl;
cout << "The user specifies how many trials or test runs are desired" << endl << endl;
cout << "The true value of PI to 8 decimal places is 3.14159265" << endl << endl;
cout << "Input a value for radius: ";
cin >> radius;
cout << endl;
cout << "How many trials would you like? ";
cin >> trials;
cout << endl << endl;
cout << "Square count gives the Total number of random samples (they are within the square)" << endl;
cout << "Circle count gives the number of random samples that also fall within the circle" << endl << endl;
while (trialcount != trials)
{
accuracy = .1;
cout << "Trial " << trialcount + 1 << endl;
cout << "Accuracy \t\t" << "Square Count \t\t" << "Circle Count \t\t" << "Pi" << endl << endl;
for (int j = 0; randpi >= pi - accuracy || randpi <= pi + accuracy; j++)
{
cout << setprecision(6) << fixed << accuracy << " \t\t" << squarecount << " \t\t" << circlecount << " \t\t" << randpi << endl << endl;
accuracy = accuracy / 10;
for (int i = 0; randpi >= pi + accuracy || randpi <= pi - accuracy; i++)
{
x = (float)(rand());
x = (x / 32767) * radius;
y = (float)(rand());
y = (y / 32767) * radius;
squarecount++;
if ((x * x) + (y * y) <= (radius * radius))
{
circlecount++;
}
randpi = float(4 * circlecount) / squarecount;
}
}
trialcount++;
}
}
我看到的问题:
第一个for
循环没有任何意义。如果你想确保使用0.1,0.01,0.001等的精度,你只需要一个简单的for
循环。以下应该做:
for ( int j = 0; j < 6; ++j )
{
...
}
x
和y
值计算错误。您希望确保它们的值小于或等于radius
。但是,当您使用时:
x = (float)(rand());
x = (x / 32767) * radius;
y = (float)(rand());
y = (y / 32767) * radius;
它们不能保证小于或等于radius
。他们将比他们不会更频繁地使用radius
。你需要使用
x = (float)(rand() % 32768);
x = (x / 32767) * radius;
y = (float)(rand() % 32768);
y = (y / 32767) * radius;
您需要在内部randpi
循环的每次迭代中重置squarecount
,circlecount
和for
的值。否则,您的计算将受到前一次迭代计算的影响。
外部for
循环必须以:
for (int j = 0; j < 6; j++)
{
accuracy /= 10;
randpi = 0;
squarecount = 0;
circlecount = 0;
必须将内部for
循环约束为仅运行一定次数。如果由于某种原因未达到准确性,您需要确保不要溢出i
。例如:
int stopAt = (INT_MAX >> 8);
for (int i = 0; (randpi >= pi + accuracy || randpi <= pi - accuracy) && i < stopAt; i++)
对于使用32位int
s的机器,这在今天的实践中是最常见的,你不会运行循环比0x7FFFFF
(十进制的8388607
)时间。
这是代码中的核心问题。您的计算有时不收敛,并且您不确定在循环的一定次数的迭代后退出。
您不需要将radius
作为程序中的变量。您可以将x
和y
计算为:
x = (float)(rand() % 32768);
x = (x / 32767);
y = (float)(rand() % 32768);
y = (y / 32767);
并更改逻辑以检查这是否是圆圈内的一个点
if ((x * x) + (y * y) <= 1.0 )
您还应该尝试仅在需要它们的范围内定义变量。这将确保您不会最终使用上一次迭代运行中的陈旧值。
以下修订程序适合我。
#include <iostream> //need this by default for cin
#include <math.h> //includes math functions
#include <cmath> //includes basic math
#include <cfloat> //includes floating point numbers
#include <iomanip> //includes setprecision for decimal places
#include <cstdlib> //needed for rand and srand functions
#include <ctime> //needed for time function used to seed generator
#include <climits>
using namespace std;
int main()
{
cout << "The purpose of this program is to estimate pi using the monte "
"carlo method and a random number generator" << endl << endl;
unsigned seed = time(0);
srand(seed);
int trialcount = 0;
int trials;
float accuracy;
const float pi = 3.14159265;
cout << "The value of PI can be found as the ratio of areas of a circle of radius r located within a square of side 2r" << endl;
cout << "This program runs a MonteCarlo Simulation that generates numbers located randomly within a square" << endl;
cout << "The count of values within the square and the count of numbers within the circle approximate their areas" << endl;
cout << "An input value of radius determines the size of the circle and square" << endl;
cout << "The user specifies how many trials or test runs are desired" << endl << endl;
cout << "The true value of PI to 8 decimal places is 3.14159265" << endl << endl;
cout << endl;
cout << "How many trials would you like? ";
cin >> trials;
cout << endl << endl;
cout << "Square count gives the Total number of random samples (they are within the square)" << endl;
cout << "Circle count gives the number of random samples that also fall within the circle" << endl << endl;
while (trialcount != trials)
{
accuracy = 0.1;
cout << "Trial " << trialcount + 1 << endl;
cout << "Accuracy \t\t" << "Square Count \t\t" << "Circle Count \t\t" << "Pi" << endl << endl;
for (int j = 0; j < 6; j++)
{
accuracy /= 10;
float randpi = 0;
int squarecount = 0;
int circlecount = 0;
int stopAt = (INT_MAX >> 8);
for (int i = 0; (randpi >= pi + accuracy || randpi <= pi - accuracy) && i < stopAt; i++)
{
float x = ((float)(rand() % 32768) / 32767);
float y = ((float)(rand() % 32768) / 32767);
squarecount++;
if ((x * x) + (y * y) <= 1.0 )
{
circlecount++;
}
randpi = float(4 * circlecount) / squarecount;
}
cout << setprecision(8) << fixed << accuracy << " \t\t" << squarecount << " \t\t" << circlecount << " \t\t" << randpi << endl << endl;
}
trialcount++;
}
}
看到它在https://ideone.com/laF27X工作。