NewtonAA 2023-10-26 19:29 采纳率: 50%
浏览 3

自写的用随机数计算圆周率大小的程序的几个问题

这是一个用随机数计算圆周率大小的程序,但是计算的结果总是3.2几,而且当我想增大某些数来使结果更加精确时,结果突然就输出4了
希望能帮我解答以下疑惑:
1)为什么算出来的数不精确
2)为什么想把某些数改大一些(没有overflow)结果就变成4了(就孤零零输出了4,小数点都没有)
3)有时候改数,输出就不见了,想问问为什么
谢谢


//because a circle is a little bit complicated, I decided to us a quarter circle to calculate the value of PI.
#include<ctime>
#include<cstdlib>
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
    //srand=(time(0));//why this can not success?
    
    srand((unsigned int)time(NULL));
    unsigned int a=0, b=0;//a and b are the coordinates of a single point
    unsigned int r=60000;//the radius of the circle
    int n=0;//the number of the points that lie in the circle
    double c=0;
    int i=0;
    for(i=0;i<=10000000;i++)
    {
        a=rand()%60001;
        b=rand()%60001;//produce two random numbers from 0 to 10000
        c=sqrt((pow(a,2)+pow(b,2)));
        if (c<=r)
        {
            n=n+1;
        }
    }
    double v=0;
    v=n/10000001.0;
    cout<<v*4<<endl;
    return 0;
}
  • 写回答

1条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2023-10-27 04:20
    关注

    【以下回答由 GPT 生成】

    问题解答:

    1) 为什么计算出来的数不是精确的圆周率?

    在你的代码中,你使用随机数来生成点坐标(a, b),然后计算点到原点的距离(c)。这个方法是通过蒙特卡洛方法估计圆周率的值。蒙特卡洛方法是一种概率性算法,它使用随机数来进行抽样和估计。由于使用的是随机数,计算出来的结果是一个近似值,而不是精确值。你使用的是一个四分之一圆作为样本,因此你得到的结果应该是圆周率的四分之一。

    如果你想获得更精确的结果,你可以增加抽样的次数。通过增加循环次数,你可以更多地抽样,从而得到更接近精确值的结果。你可以尝试增加循环次数,看看是否能够获得更准确的结果。

    2) 为什么当我想把某些数增大(没有溢出)以获得更精确的结果时,结果却变成了4(没有小数点)?

    在你的代码中,你将抽样点的坐标限制在了0到60000之间。这是因为你使用了取余操作rand()%60001来生成随机数,这样得到的数值范围就是0到60000。当你增大这些数时,可能会超过60000的范围。在C++中,整数的溢出操作是未定义行为,这意味着你无法预测溢出后会得到什么结果。因此,当你的数值超过限制范围时,你的程序可能会产生不确定的结果。

    为了避免溢出问题,你可以尝试使用更大的数据类型,比如unsigned long long来存储坐标和半径。这样可以扩大数值范围,但是也会增加计算的复杂度和内存的消耗。

    3) 有时候改变某些数后,输出结果就消失了,我想知道这是为什么。

    在你的代码中,你使用了unsigned int类型来存储坐标和半径。unsigned int类型的范围是0到4294967295,当你尝试增大某些数时,可能会导致溢出。溢出会导致数值变为0或者其他不可预测的结果,这可能会导致计算结果消失或者变得不可靠。

    为了避免溢出问题,你可以尝试使用更大的数据类型,如unsigned long long来存储坐标和半径。这将扩大数值的范围,避免溢出,使计算更加可靠。

    以下是优化后的代码示例:

    #include <ctime>
    #include <cstdlib>
    #include <iostream>
    #include <cmath>
    using namespace std;
    
    int main()
    {
        srand((unsigned int)time(NULL));
    
        unsigned long long a = 0, b = 0; // a和b是一个单点的坐标
        unsigned long long r = 60000;   // 圆的半径
        unsigned long long n = 0;        // 落在圆内的点的数量
    
        for (unsigned long long i = 0; i <= 10000000; i++)
        {
            a = rand() % (r + 1);
            b = rand() % (r + 1); // 从0到半径r产生两个随机数
            double c = sqrt((pow(a, 2) + pow(b, 2)));
    
            if (c <= r)
            {
                n++;
            }
        }
    
        double v = static_cast<double>(n) / 10000001.0;
        cout << v * 4 << endl;
    
        return 0;
    }
    

    在优化后的代码中,我将坐标和半径的类型改为unsigned long long,这将扩大数值的范围,避免溢出导致的问题。我还修改了随机数生成的范围,确保生成的坐标在0到半径r之间。此外,我将循环变量的类型从int改为了unsigned long long,以适应更大范围的计算。

    希望这些优化后的代码可以解决你的问题,如果还有其他问题,请随时提问。



    【相关推荐】



    如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^
    评论

报告相同问题?

问题事件

  • 创建了问题 10月26日

悬赏问题

  • ¥15 TeleScan不能修改bar
  • ¥100 请问我基于逐飞库写的这个有关于mp u6050传感器的函数,为什么输出的值是固定的?
  • ¥15 hadoop中启动hive报错如下怎么解决
  • ¥15 如何优化QWebEngineView 加载url的速度
  • ¥15 关于#hadoop#的问题,请各位专家解答!
  • ¥15 如何批量抓取网站信息
  • ¥15 Spring Boot离线人脸识别
  • ¥15 使用Ant Design Pro vue的时候,使用环境变量的时候,构建报错是什么原因
  • ¥15 NRF24L01能发送但是不能接收
  • ¥15 想问一下这种情况怎么解决呢(关键词-file)