我是C ++的新手。我正在尝试使用计算机系统的随机数生成器基于Ernesto Cesaro的定理来统计确定Pi的值。但我现在所做的可以输入种子数并生成100个伪随机数,然后估计pi的值。生成器可以生成不同组的伪随机数。然而,令人困惑的是我总是得到2.8284的pi估计而没有变化。这是代码:
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
int seed;
cout << "input a seed number: " << endl;
cin >> seed;
srand(seed);
int i, a[100];
for (i = 0; i < 100; i++)
a[i] = rand() % 100 + 1;
cout << "The generated random numbers are: " << endl;
for (i = 0; i < 100; i++)
cout << a[i] << "\t";
int m, n, j, r;
int sum = 0;
for (j = 0; j < 100; j++)
{
m = a[j];
n = a[j + 1];
j = j + 2;
do
{
r = m%n;
m = n;
n = r;
} while (r != 0);
if (n = 1)
sum = sum + 1;
}
double Pi, p;
p = 300 / sum;
Pi = sqrt(p);
cout << "The estimate value of Pi is: " << Pi << endl;
system("pause");
return 0;
}
请注意,Cesaro定理指出,给定两个随机整数x和y,gcd(x,y)= 1的概率为6 /(Pi ^ 2)。并且使用的PRNG影响得到的估计与Pi的接近程度(3.1416)。
答案 0 :(得分:5)
您的代码存在一些问题。
问题#1:
if (n = 1)
应为if (n == 1)
,否则您将1
分配给n
并始终评估为真。
问题#2:
n = r;
} while (r != 0);
if (n == 1)
如果您考虑一下,只有当r
为0
时,循环才会结束,但由于循环的最后一行,n
也将0
。因此n
永远不会等于1
。您可能需要if (m == 1)
。
问题#3:
for (j = 0; j < 100; j++)
{
...
j = j + 2;
您正在递增j
行和循环体中的for
。你只需要一个。
for (j = 0; j < 100; j += 2)
{
//no j increment
问题#4:
p = 300 / sum;
这是一个整数除法,因为两个数都是整数。你想要煽动点:p = 300.0 / sum;
。
随着这些变化我得到3.16
。
答案 1 :(得分:0)
算法中有两个错误。 (不是四:p)
首先 - 当gcd不大于1时,数字是互质的,你也应该检查m
值而不是n
(参见rodrigo的回答)。所以你需要改变这个:
if (m <= 1)
sum = sum + 1; // ++sum;
第二个错误是您的估算工具:p = 300 / sum;
。你为什么用300?正确的是:
float pi = sqrt ( 6.f * iterations / sum) // from p = 6 / pi^2
代码中的iterations
为34(因为您更改了j
- 循环体中的索引)。
答案 2 :(得分:0)
问题是你的形状错了。您可以成功地估算出方形圆周与其对角线的比率,而不是圆周长与其直径(pi)的比值。
即。边1的正方形的周长为4,它的对角线为:
sqrt(1 ^ 2 + 1 ^ 2)= sqrt(2)
因此,周长与对角线的比率为:
4:sqrt(2)= 2.8284
只需将方块更改为圆形即可。