gpt4 book ai didi

c++ - 用蒙特卡洛方法估计 Pi,循环似乎提前终止

转载 作者:行者123 更新时间:2023-11-30 04:49:07 26 4
gpt4 key购买 nike

我正在尝试编写一个程序,通过随机数生成器根据蒙特卡洛方法估算 Pi。我试图在 1、2、3、4、5 和 6 位数字的精度内估算 Pi,并让程序在屏幕上打印出需要多少点才能达到 Pi 的 .1 位数字,然后是 Pi 的 .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++;

}


}

最佳答案

我看到的问题:

问题1

第一个 for 循环没有任何意义。如果您想确保使用 0.1、0.01、0.001 等精度,您只需要一个简单的 for 循环。应执行以下操作:

for ( int j = 0; j < 6; ++j )
{
...
}

问题2

xy 值计算不正确。您要确保它们的值小于或等于 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;

问题3

您需要在内部 for 的每次迭代中重置 randpisquarecountcirclecount 的值> 循环。否则,您的计算将受到上一次迭代计算的影响。

外层 for 循环必须以:

for (int j = 0; j < 6; j++)
{
accuracy /= 10;
randpi = 0;
squarecount = 0;
circlecount = 0;

问题4

内部 for 循环必须被限制为只能运行一定次数。如果由于某种原因没有达到准确性,您要确保不会溢出 i。例如:

int stopAt = (INT_MAX >> 8);
for (int i = 0; (randpi >= pi + accuracy || randpi <= pi - accuracy) && i < stopAt; i++)

对于使用 32 位 int 的机器,这是当今实践中最常见的,您不会运行循环超过 0x7FFFFF( 8388607 十进制)次。

这是您代码中的核心问题。您的计算有时不会收敛,并且您无法确保在一定次数的循环迭代后退出。

进一步改进

您不需要将 radius 作为程序中的变量。您可以将 xy 计算为:

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 查看它的工作情况.

关于c++ - 用蒙特卡洛方法估计 Pi,循环似乎提前终止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55527800/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com