算法设计与分析:随机化算法(作业-必做)(头歌实验)

本文介绍了三个编程任务,分别是使用伪随机数模拟抛硬币实验以计算正面出现的概率,用随机投点法估算圆周率,以及解决非线性方程组的问题。这些任务涉及到随机数生成、概率统计和数值计算方法在IT技术中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第1关:硬币实验

任务描述

本关任务:计算机产生的伪随机数来模拟抛硬币试验。

相关知识

为了完成本关任务,你需要掌握:1.如何获取数组的长度,2.如何遍历数组。

随机数

随机数在随机化算法设计中扮演着十分重要的角色。 在现实计算机上无法产生真正的随机数,因此在随机化算法中使用的随机数都是一定程度上随机的,即伪随机数。

用计算机产生的伪随机数来模拟抛硬币试验。 假设抛10次硬币,每次抛硬币得到正面和反面是随机的。拋10次硬币构成一个事件。 调用Random(2)返回一个二值结果。 在主程序中反复调用函数TossCoins模拟拋10次硬币这一事件50000次。 用head[i](0<=i<=10)记录这50000次模拟恰好得到i次正面的刺手。最终输出模拟抛硬币事件得到的正面事件的概率图。

编程要求

根据提示,在右侧编辑器补充代码。

测试说明

RandomNumber.h 函数已经写好,可以点击查看。

平台会对你编写的代码进行测试: 例如: 输入: 10 50000 输出:

 
  1. 0 *
  2. 1 *
  3. 2 *
  4. 3 *
  5. 4 *
  6. 5 *
  7. 6 *
  8. 7 *
  9. 8 *
  10. 9 *
  11. 10 *`

开始你的任务吧,祝你成功!

参考答案:

#include "RandomNumber.h"
#include <iostream>
using namespace std;
int TossCoins(int numberCoins);
int main()
{
    //模拟随机抛硬币事件
    int NCOINS;
    long NTOSSES;
    cin >>NCOINS;
    cin >>NTOSSES;
    //heads[i]是得到i次正面的次数
    long i,heads[NCOINS+1];
    int j,position;
    //初始化数组heads
    for(int j=0; j<NCOINS+1;j++)
    {
        heads[j] = 0;
    }
    //重复50,000次模拟事件
    for(int i=0; i<NTOSSES; i++)
    {
        heads[TossCoins(NCOINS)]++;
    }
    //输出频率图
    for(int i=0; i<=NCOINS; i++)
    {
        position = int(float(heads[i])/NTOSSES*72);
        cout<<i<<" ";
        for(int j=0; j<position-1; j++)
        {
            cout<<" ";
        }
        cout<<"*"<<endl;
    }
    return 0;
}
int TossCoins(int numberCoins)
{
    //随机抛硬币
    static RandomNumber coinToss(1);
    int i,tosses = 0;
    for(int i=0; i<numberCoins; i++)
    {
        //Random(2) = 1表示正面
        tosses += coinToss.Random(2);
    }
    return tosses;
}

第2关:用随机投点法求圆周率

任务描述

本关任务:编写一个程序,利用随机投点法计算圆周率

相关知识

设有一半径为r的圆及其外切四边形。向该正方形随机地投掷n个点。设落入圆内的点数为k。由于所投入的点在正方形上均匀分布,因而所投入的点落入圆内的概率为:

所以当n足够大时,k与n之比就逼近这一概率,从而

编程要求

根据提示,在右侧编辑器补充代码。

测试说明

平台会对你编写的代码进行测试:

输入:

100

输出:

n1=100 pi=3.12

开始你的任务吧,祝你成功!

参考答案:

//随机化算法 用随机投点法计算π值
#include "RandomNumber.h"
#include <iostream>
using namespace std;
 
double Darts(int n);
 
int main()
{
	int n1;
    cin>> n1;
    cout<<"n1="<<n1<<"\npi="<<Darts(n1)<<endl;
	return 0;
}
 
//用随机投点法计算π值
double Darts(int n)
{	
	static RandomNumber dart(1);
   /*************begin****************/
   int k=0;
   for(int i=1;i<=n;i++){
       double x=dart.fRandom();
       double y=dart.fRandom();
       if((x*x+y*y)<=1){
           k++;
       }
   }
   return 4*k/double(n);
   
   /***************end****************/
}

第3关:解非线性方程组

任务描述

本关任务:编写程序求线性方程组。

相关知识

求解下面的非线性方程组

其中,x1,x2,…,xn是实变量,fi是未知量x1,x2,…,xn的非线性实函数。 要求确定上述方程组在指定求根范围内的一组解 。

解决这类问题有多种数值方法,如:牛顿法、拟牛顿法、粒子群算法等。最常用的有线性化方法和求函数极小值方法。为了求解所给的非线性方程组,构造一目标函数

式中,x=(x1,x2,……xn)。易知,上式取得极小值点即是所求非线性方程组的一组解。

编程要求

求一个简单的二维线性方程组: x1-x2=fx1 x1+x2=fx2 根据提示,在右侧编辑器补充代码。

测试说明

平台会对你编写的代码进行测试: 例如: 输入: 1 3 输出: The original equations are: x1-x2=1 x1+x2=3 The roots are: x1=2.02104 x2=1.01445 开始你的任务吧,祝你成功!

参考代码:

//随机化算法 解线性方程组
#include "RandomNumber.h"
#include <iostream>
using namespace std;
 
bool NonLinear(double *x0,double *dx0,double *x,double *fx,double a0,
					double epsilon,double k,int n,int Steps,int M);
double f(double *x,double *fx);
 
int main()
{
	double  *x0,				//根初值
			*x,					//根
			*dx0,			//增量初值
			*fx,  // 函数值
			a0 = 0.0001,			//步长
			epsilon = 0.01,		//精度
			k = 1.1;			//步长变参
	int n = 2,					//方程个数
		Steps = 10000,			//执行次数
		M = 1000;				//失败次数
 
	x0 = new double[n+1];
	dx0 = new double[n+1];
	x = new double[n+1];
	fx = new double[n+1];
	
	cin >> fx[1];
	cin >> fx[2];
	
	//根初值
	x0[1] = 0.0;
	x0[2] = 0.0;
 
	//增量初值
	dx0[1] = 0.01;
	dx0[2] = 0.01;
 
	cout<<"The original equations are:"<<endl;
	cout<<"x1-x2="<<fx[1]<<endl;
	cout<<"x1+x2="<<fx[2]<<endl;
 
	cout<<"The roots are:"<<endl;
 
	bool flag = NonLinear(x0,dx0,x,fx,a0,epsilon,k,n,Steps,M);
	while(!flag)
	{		
		flag = NonLinear(x0,dx0,x,fx,a0,epsilon,k,n,Steps,M);
	}	
	for(int i=1; i<=n; i++)
	{
		cout<<"x"<<i<<"="<<x[i]<<" ";
	}
	cout<<endl;
 
	return 0;
}
 
//解非线性方程组的随机化算法
bool NonLinear(double *x0,double *dx0,double *x,double *fx,double a0,
					double epsilon,double k,int n,int Steps,int M)
{
	static RandomNumber rnd(1);
	bool success;			//搜索成功标志
	double *dx,*r;
 
	dx = new double[n+1];	//步进增量向量
	r = new double[n+1];	//搜索方向向量
	int mm = 0;				//当前搜索失败次数
	int j = 0;				//迭代次数
	double a = a0;			//步长因子
 
	for(int i=1; i<=n; i++)
	{
		x[i] = x0[i];
		dx[i] = dx0[i];
	}
 
	double fy = f(x,fx);		//计算目标函数值
	double min = fy;		//当前最优值
 
	while(j<Steps)
	{
		//(1)计算随机搜索步长
	/***********begin**************/
	if(fy<min){
        min=fy;
        a*=k;
        success=true;
    }
    else{
        mm++;
        if(mm>M){
            a/=k;
        }
        success=false;
    }
    if(min<epsilon){
        break;
    }
	/************end***************/
		//(2)计算随机搜索方向和增量
	/***********begin**************/
	for(int i=1;i<=n;i++){
        r[i]=2.0*rnd.fRandom()-1;
    }
    if(success){
        for(int i=1;i<=n;i++){
            dx[i]=a*r[i];
        }
    }
    else {
        for(int i=1;i<=n;i++){
            dx[i]=a*r[i]-dx[i];
        }
    }
	/************end***************/
 
		//(3)计算随机搜索点
	/***********begin**************/
	for(int i=1;i<=n;i++){
        x[i]+=dx[i];
    }
	/************end***************/
 
		//(4)计算目标函数值
	/***********begin**************/
	fy=f(x,fx);
    j++;
	/************end***************/
	}	
 
	if(fy<=epsilon)
	{
		return true;
	}
	else
	{
		return false;
	}
}
 
double f(double *x, double* fx)
{
	/***********begin**************/
	return (x[1]-x[2]-fx[1])*(x[1]-x[2]-fx[1])
            +(x[1]+x[2]-fx[2])*(x[1]+x[2]-fx[2]);
	/************end***************/
}

如果对你有所帮助,感谢点赞加收藏!

算法设计与分析:随机化算法(作业-必做)(头歌实验) -文章频道 - 我的学习圈 - 个人学习圈 (writebug.com)icon-default.png?t=N7T8https://www.writebug.com/article/8c2ca050-f3e6-11ed-a099-0242ac14000d

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值