蒙特卡洛算法

        蒙特卡洛算法并不是一种算法的名称,而是是一类随机方法的统称。这类方法的特点是在随机采样上计算得到近似结果。随着采样的增多,得到的结果是正确结果的概率逐渐加大,但在获得真正的结果之前(放弃随机采样,而采用类似全采样这样的确定性方法),无法知道目前得到的结果是不是正确的结果

        从特性来说,既然是随机算法,在采样不全时,通常不能保证找到最优解,只能尽量找。因此可将随机算法分成以下两类:

        (1)蒙特卡洛算法:采样越多,越近似最优解(尽量找好的,但不保证是最好的)

        对一百个数进行比较,首先随机取一个数A,再随机取一个数B与A进行比较,留下较大值,抛弃掉较小值,然后再随机取一个数C与较大值作比较,如此循环,保证留下的值都比舍弃掉的值大,比较的次数越多,值就越大。但在一百个数全部取出前,无法确认目前留下的值是否是最大值

        (2)拉斯维加斯算法:采样越多,越有机会找到最优解(尽量找最好的,但不保证能找到)

        假设有一把锁和一百把钥匙,其中只有一把钥匙能开锁,每次随机拿一把钥匙开锁,失败则舍弃,如此循环,尝试的次数越多,则打开(找到最优解)的机会越大。当然,也有可能这一百把钥匙都打不开锁(无法找到最优解)

        因为随机算法的特性,所以算法本身可能复杂,也可能简单

        下面就编写一个Java程序来实现蒙特卡洛法求π的近似值:

        这个方法的理论基础是概率论中的伯努利大数定律。

        在一个边长为1的正方形中有一个内切圆,根据圆的面积公式= πr2,可得该圆的面积为π/4。假设有大量的随机点等概率均匀地落入此正方形中,若正方形的面积为S,内切圆的面积为S',落入正方形中的点数为N',落入内切圆的的点数为N,这时便有 S'/S = N'/N,所以可据此求得 π = 4N'/N

import java.io.BufferedReader;
import java.io.InputStreamReader;
 
public class MonteCarloPi {
 
	public static void main(String[] args) throws Exception {
		double radius = 1.0;
        int pointNumber = 100000000
		Circular c = new Circular(radius);
		
		for(int i = 1; i <= numberOfDarts; i++) {
			Point p = Point.getRandom(radius);
			c.strike(p);
		}
		
		double fractionIn = c.getFractionIn();
		double pi = 4.0 * fractionIn;
		System.out.println("Pi is approximately " + pi);
	}
 
}
 
class Circular {
	
	private double radius;
	private int insideCircle, outsideCircle;
	
	public Circular(double radius) {
		this.radius = radius;
		insideCircle = 0;
		outsideCircle = 0;
	}
	
	public void strike(Point point) {
		double x = point.getX();
		double y = point.getY();
		
		if (Math.sqrt(x*x + y*y) < radius)
			insideCircle++;
		else
			outsideCircle++;
	}
	
	public double getFractionIn() {
		double total = (double) (insideCircle + outsideCircle);
		return (double) insideCircle / total;
	}
}
 
class Point {
	
	private double x,y;
	
	public Point(double x, double y) {
		this.x = x;
		this.y = y;
	}

	public double getX() {
        return x;
    }

	public double getY() {
        return y;
    }
	
	public static Point getRandom(double radius) {
		
		double x, y;
		double size = Math.random();
		double sign = Math.random();
		size = size * radius;
		
		if(sign > 0.5)
			x = size;
		else
			x = -size;
		
		size = Math.random();
		sign = Math.random();
		size = size * radius;
		
		if (sign > 0.5)
			y = size;
		else
			y = -size;
		
		return new Point(x, y);
	}
}

执行上述代码可得:Pi is approximately 3.14170216

由此可见,所得到的结果近似于圆周率π

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值