IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 基于C语言的产生任意均值与方差的正态分布的随机数,生成的随机数可基于任意范围或指定范围 -> 正文阅读

[C++知识库]基于C语言的产生任意均值与方差的正态分布的随机数,生成的随机数可基于任意范围或指定范围

1.目的

? ? ? ? 因为项目需要,需要产生一串随机数,此随机数非均匀分布,而是基于正态分布,同时该随机数需要在指定区间内。

?2.结果展示

? ? ? ? 我的项目中,希望产生一个正态分布的随机数,范围在[20,240],那么正态分布的均值就是130((20+240)/2),经过不断调试结果,设置标准差为50。

? ? ? ? ?上图就是产生的随机数正态分布。

? ? ? ? ? 假如不设置取值范围。见下图:

? ? ? ? 改变标准差到100,让其变得更“胖”。效果如下:

? ? ? ? 通过上述展示,达到了设计目的。

3.实现

3.1 源码

/*
# THIS FILE IS PART OF RANDN PROJECT
# randn - The core part of the GCC
# THIS PROGRAM IS UNFREE SOFTWARE, IS LICENSED UNDER Ding Zhenjin(dingzj2000@163.com)
# YOU SHOULD HAVE RECEIVED A COPY OF RANDN LICENSE, IF NOT, PLEASE DO NOT USE.
#YOU SHOULD BUY THE COPYRIGHT
# Copyright (c) 1987-2087
# Copyright (c) 2021 Ding Zhenjin(dingzj2000@163.com)
*/

/*
2021.7.9
任意范围的正态分布随机数
环境:Ubuntu32 16.04.1  cairo库实现
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <cairo.h>

#include <math.h>
#include <time.h>

#include "randn.h"

/* 采集样本数量 */
#define N 100

/*
背景图标是1300*600
*/

/* 原点坐标 */
#define OriginX    650  //原点居中
#define OriginY    20

/* 坐标转换 */
#define X(n)     ((n)*1.0)
#define Y(n)     ((600-(n))*1.0)

/* 坐标系内位置 */
#define PosX(n)  (X(OriginX+(n)))
#define PosY(n)  (Y(OriginY+(n)))

#define ANGLE(ang)  (ang * 3.1415926 / 180.0)


#define OFFSET    600

struct POS{
	int x;
	int y;
};

cairo_surface_t *image_surface_create_from_png(const char *filename)
{
	cairo_status_t cst;

	cairo_surface_t *image_sf=cairo_image_surface_create_from_png(filename);
	cst = cairo_surface_status (image_sf);
	if (cst!=CAIRO_STATUS_SUCCESS)
	{
		printf(	"failed to cairo_image_surface_create_from_png cairo_status_t is:%d file: %s",cst, filename);
		image_sf = NULL;
		//if (cst == CAIRO_STATUS_NO_MEMORY) {
			//image_sf = cairo_image_surface_create_from_jpeg(filename);
		//}
	}
	return image_sf;
}



void draw_png2surface(cairo_t *cr, double x, double y, cairo_surface_t *surface){
	if(surface != NULL){
		cairo_set_source_surface(cr, surface, x, y);
		cairo_paint(cr);
	}
}

/*
创建背景
*/
void createBackground(cairo_t *cr,char *file)
{
	cairo_surface_t  *g_background;

	if(cr == NULL || file == NULL)
	{
		return;
	}

	/* 背景图 */
	g_background = image_surface_create_from_png(file);
	draw_png2surface(cr, 0, 0, g_background);
}

/*
构建坐标系
*/
void createCoordinate(cairo_t *cr)
{
	char tempbuf[64];

	if(cr == NULL)
	{
		return;
	}

	/* 划线 */
	cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);/* 设置颜色 -黑色 */
	cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
	cairo_set_line_width (cr, 1.0);
	cairo_move_to (cr, X(OriginX-OFFSET), Y(OriginY));//X轴
	cairo_line_to (cr, X(OriginX+OFFSET), Y(OriginY));
	cairo_stroke (cr);

	cairo_move_to (cr, X(OriginX), Y(OriginY));//Y轴
	cairo_line_to (cr, X(OriginX), Y(OriginY+550));
	cairo_stroke (cr);

	/* 量程 */
	cairo_select_font_face (cr, "serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
	cairo_set_font_size (cr, 15.0);
	//原点
	cairo_move_to (cr, X(OriginX-5), Y(OriginY-15));
	cairo_show_text (cr, "0");

	//负X轴
	cairo_move_to (cr, X(OriginX-OFFSET-15), Y(OriginY-15));
	sprintf(tempbuf,"%d",-OFFSET);
	cairo_show_text (cr, tempbuf);
	//正X轴
	cairo_move_to (cr, X(OriginX+OFFSET-15), Y(OriginY-15));
	sprintf(tempbuf,"%d",OFFSET);
	cairo_show_text (cr, tempbuf);


	//Y轴
	cairo_move_to (cr, X(OriginX-10), Y(OriginY+550+5));
	cairo_show_text (cr, "550");
	cairo_stroke (cr);
}


/*
构建坐标点
*/
void createPoints(cairo_t *cr,int x,int y)
{
	char buf[64];

	if(cr == NULL)
	{
		return;
	}

	cairo_set_source_rgb(cr, 0.0, 0.0, 1.0);/* 设置颜色 -蓝色 */
	cairo_set_line_width(cr, 1);
	cairo_arc(cr, PosX(x), PosY(y), 1, ANGLE(0), ANGLE(360));
	cairo_stroke (cr);

	/* 显示坐标 */
	memset(buf,0x00,sizeof(buf));
	sprintf(buf,"(%d,%d)",x,y);
	cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);/* 设置颜色 -黑色 */
	cairo_select_font_face (cr, "serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
	cairo_set_font_size (cr, 2.0);
	cairo_move_to(cr,PosX(x-8), PosY(y+8));
	cairo_show_text (cr, buf);
	cairo_stroke (cr);
}

/*
构建坐标系Y直线

*/
void createLine(cairo_t *cr,int start_x,int start_y,int end_x,int end_y)
{
	if(cr == NULL)
	{
		return;
	}


	/* 划线 */
	cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);/* 设置颜色 -红色 */
	cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
	cairo_set_line_width (cr, 1.0);
	cairo_move_to (cr, PosX(start_x), PosY(start_y));
	cairo_line_to (cr, PosX(end_x), PosY(end_y));
	cairo_stroke (cr);
}

/*
创建正态分布曲线
*/
void createNormalCurve(cairo_t *cr,int start_x,int start_y,int end_x,int end_y)
{

}

/*
指数和对数函数测试
*/
int mathTest(void)
{
	printf("pow(x,y) x= 10,y=2  value=%lf\n",pow(10.0,2.0));
	printf("powl(x,y) log x=10,y=100  value=%lf\n",powf(100.0,2.0));

	printf("exp(x) e x=1  value=%f\n",exp(1));
	printf("exp(x) e x=2  value=%f\n",exp(2));

	printf("loge=%f\n",log(10)); //以e为底的对数函数
	printf("loge=%f\n",log(2.718282)); //以e为底的对数函数
	printf("log10=%f\n",log10(100)); //以10为底的对数函数

	printf("sqrt=%f\n",sqrt(16));//平方根
}


int main(int argc,char *argv[])
{
	int rand_sum[OFFSET*2+1]={0};
	int i,j,i_randn;

	double u,g,r,o,d_randn,dec;


	/************************ 创建cairo ****************************/
	cairo_surface_t *surface =	cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1300, 600);
	cairo_t *cr = cairo_create (surface);

	/*********************** 创建背景 *****************************/
	createBackground(cr,"background.png");

	/*********************** 构建坐标系 *****************************/
	createCoordinate(cr);


	/**************************** 设置随机数种子 ***************************/
	/* 最同一轮显示效果中,随机数种子应该保持一致!!!! */
	srand(time(0));
	r = rand();
	//r = 5.0;//

	/**************************** 正态分布参数设置 ***************************/
	u = 130.0;//均值
	g = 100;   //标准差

	/**************************** 设置随机数范围 ***************************/
	o = 0.0;  //设置为0,表示为生成的随机数在任意范围,非0,表示产生的随机数在[u-o,u+o]之间

	for(i = 0; i < 12000; i++)
	{
		for(j = 0; j < 5; j++)
		{
			d_randn = randn(u,g,&r);
			printf("%10.7lf ",d_randn);

			//设置随机数范围
			if(o != 0.0)
			{
				if(d_randn < u-o || d_randn > u+o)
				{
					continue;
				}
			}

			i_randn = (int)d_randn;
			dec = d_randn-i_randn;
			if(dec > 0.5)
			{
				i_randn++;
			}

			if(i_randn >= -OFFSET && i_randn  <= OFFSET)
			{
				rand_sum[OFFSET+i_randn] = rand_sum[OFFSET+i_randn]+1;
			}
		}

		printf("\n");
	}

	/************************ 对找出的随机数进行绘点 ****************************/
	for(i = 0; i < sizeof(rand_sum)/sizeof(int); i++)
	{
		if(rand_sum[i] == 0)
		{
			continue;
		}

		createLine(cr,i-OFFSET,0,i-OFFSET,rand_sum[i]);
	}

	/************************ 创建图片 ****************************/
	cairo_surface_write_to_png (surface, "randn.png");

	/************************ 销毁cairo ****************************/
	cairo_destroy (cr);
	cairo_surface_destroy (surface);

	return 0;
}

3.2 cairo库

????????基于Linux C编程,图像显示使用cairo库。至于如何使用不在本文论述的重点。详见:

????????https://blog.csdn.net/dingzj2000/article/details/103719104

3.3 随机数种子

? ? ? ? 谈到随机数,必然有随机数种子,代码里用时间产生种子,是为了每一轮结果(一轮60000个点)产生不同的效果。在我的项目中,一轮是从开机到关机整个流程,在设置好初始随机数种子后,就不要在改变。

	/**************************** 设置随机数种子 ***************************/
	/* 最同一轮显示效果中,随机数种子应该保持一致!!!! */
	srand(time(0));
	r = rand();
	//r = 5.0;//

3.4 显示原理

? ? ? ? 产生的随机数是浮点型,然后强制转换为整型,这个整型对应的像素坐标就加1,在一轮显示后,显示所有像素。

? ? ? ? 因为浮点型强制转换为整型,简单做了一个四舍五入。在实际项目中可以不用。

i_randn = (int)d_randn;
dec = d_randn-i_randn;
if(dec > 0.5)
{
	i_randn++;
}

if(i_randn >= -OFFSET && i_randn  <= OFFSET)
{
	rand_sum[OFFSET+i_randn] = rand_sum[OFFSET+i_randn]+1;
}

3.4 函数参数定义

????????double randn(double u,double g,double *r)

? ? ? ? 参数比较简单:

? ? ? ? u是正态分布平均值;

? ? ? ? g是正态分布标准差;

? ? ? ? *r是随机数种子

/**************************** 正态分布参数设置 ***************************/
u = 130.0;//均值
g = 100;   //标准差

/**************************** 设置随机数范围 ***************************/
o = 0.0;  //设置为0,表示为生成的随机数在任意范围,非0,表示产生的随机数在[u-o,u+o]之间

3.5 输出结果打印

????????

4.核心算法

????????采用C语言实现,见下图:

5.获取算法

加微信(微信号:dingzj2000),获取详细算法。

?

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-10 14:21:50  更:2021-07-10 14:24:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/4 19:10:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码