正态分布标准公式
μ代表均数,σ代表标准差。
Box-Muller算法生成符合正太分布随机数公式
代码实现
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace BoxMullerTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
protected override void OnPaint(PaintEventArgs e)
{
float offsetX = 200;
float offsetY = 0;
float scaleX = 50;
float scaleY = 700;
//标准正态分布公式生成图像(红色)
for (double x = -5; x <= 5; x += 0.05)
{
double y = NormalDistribution(x);
PaintPoint(e, (float)x * scaleX + offsetX, (float)y * scaleY + offsetY);
}
//BoxMuller算法生成图像(绿色)
for (double i = 0; i < 100; i++ )
{
Point p = BoxMuller.RandPoint();
PaintPoint1(e, (float)p.x * 20 + 180, (float)p.y * 10+ 50);
}
}
public void PaintPoint(PaintEventArgs e, float x, float y)
{
Graphics g = e.Graphics;
Pen myPen = new Pen(Color.Red, 1);
g.DrawEllipse(myPen, x, y, 3, 3);
}
public void PaintPoint1(PaintEventArgs e, float x, float y)
{
Graphics g = e.Graphics;
Pen myPen = new Pen(Color.Green, 1);
g.DrawEllipse(myPen, x, y, 3, 3);
}
/// <summary>
/// 通过x值求正态分布的y值
/// </summary>
/// <param name="x">输入值</param>
/// <param name="miu">均数</param>
/// <param name="sigma">标准差</param>
/// <returns></returns>
public static double NormalDistribution(double x, double miu = 0, double sigma = 1)
{
//正态分布公式
double y = 1.0 / Math.Sqrt(2 * Math.PI * sigma * sigma) / sigma * Math.Exp(-1 * (x - miu) * (x - miu) / (2 * sigma * sigma));
return y;
}
}
public class Point
{
public double x;
public double y;
public Point(double x, double y)
{
this.x = x;
this.y = y;
}
}
/// <summary>
/// Box-Muller算法是一种能根据均匀分布的随机数来产生正态分布的随机数的算法。
/// 根据Box-Muller算法,假设a、b是两个服从均匀分布并且取值范围为从0到1的随机数,
/// 我们就可以通过下面的公式获得两个满足正态分布(均数为0,标准差为1)的随机数x和y
/// </summary>
public class BoxMuller
{
static Random rd;
static BoxMuller()
{
rd = new Random();
}
/// <summary>
/// 生成符合正态分布的随机数(均数为0,标准差为1)
/// </summary>
/// <returns></returns>
public static Point RandPoint()
{
//生成两个随机数范围0到1
double a = rd.NextDouble();
double b = rd.NextDouble();
//在以半径为radius的圆上取随机角度的点
double radius = Math.Sqrt(-2 * Math.Log(a));
double angle = 2 * Math.PI * b;
double z0 = angle * Math.Cos(angle);
double z1 = angle * Math.Sin(angle);
Point p = new Point(z0, z1);
return p;
}
}
}
运行效果