码迷,mamicode.com
首页 > 其他好文 > 详细

Halton Sequence 原理和代码实现

时间:2015-08-11 18:55:33      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:mapreduce   算法   halton   sequence   随机   

Halton Sequence是一种随机序列,被用来生成均匀分布的随机数。最常被应用的地方就是Monte Carlo算法。因为最近在学习MapReduce算法,在看对PI的计算实现时了解到Halton Sequence,但惊讶地发现Google竟然搜不到多少介绍,不知道是已经没什么人用了,还是比较冷门呢。Anyway,hadoop计算PI用到了,所以我也就了解下啦。

Halton Sequence经常被用来选取空间中的均匀随机点。但其实我理解它不是一种随机选取算法,因为它更强调平均,是通过一定的算法让所选取的点精确地均匀分布在空间里。


算法

Halton算法其实不难,就是选取一个质数作为基数,然后不断地切分,从而形成一些不重复并且均匀的点,每个点的坐标都在0~1之间。

比如,在一个一维数轴上,取2作为基数。那么首先对(0,1)进行切分,得到1/2;然后对(0,1/2)和(1/2,1)进行切分,得到1/4和3/4;然后在对(0,1/4), (1/4, 1/2), (1/2, 3/4)和(3/4,1)进行切分...最终得到的数列为:

1?21?43?41?85?83?87?81?169?16,...

同理,以3为基数得到的数列为:

1?32?31?94?97?92?95?98?91?27,...


实现

算法的原理不难,但编程实现就不那么简单了。至少我观察了很久也没发现这一组数组该怎么快速实现,wiki上的伪码也太糙了,看不懂。查了很久,才查到一点简单的说明,琢磨了下,现在分享出来:

要取第n个数:

  • 首先要把n化为b进制数,其中b就是指定的基数。
  • 然后把转化后的数反转到小数点后,转化为小数。
  • 最后,再把这个b进制数转回成十进制数。

比如,以2为基数,取第6个数,首先转化为2进制数为110. 然后把110反转到小数点后成了0.011,这是二进制数。然后把二进制的0.011转化为十进制,就是 0.5*0 + 0.25*1 + 0.125*1=0.375 。所以第六个数就是0.375.


到这里其实就很清晰了,我们把第一步和第二步合并一下,就是:

第n个数 = 求和{ b进制 * 每一位的进位取负次方}

例如上面以2为基数的第6个数(110):

= 1 * 1/2^2 + 1 * 1/2^1 + 0*1/2^0. 


代码

下面是二维Halton Sequence的java代码实现。基数可以自己指定:


<span style="font-family:Courier New;font-size:14px;">public class HaltonSequence {
	static int digit = 40;
	private int[] bases= new int[2];
	private double[] baseDigit = new double[2];
	private double[][] background = new double[2][digit];
	private long index;
	
	HaltonSequence(int[] base) {
		bases = base.clone();
		index = 0;

		for(int i=0; i<bases.length; i++) {
			double b = 1.0/bases[i];
			baseDigit[i] = b;
			for(int j=0; j<digit; j++) {
				background[i][j] = j == 0 ? b : background[i][j-1]*b;
			}
		}
	}
	
	double[] getNext() {
		index++;
		
		double[] result = {0,0};

		for(int i=0; i<bases.length; i++) {
			long num = index;
			int j = 0;
			while(num != 0) {
				result[i] += num % bases[i] * background[i][j++];
				num /= bases[i];
			}
		}
		
		return result;
	}
	
	public static void main(String[] args) {
		int[] base = {2,5};
		HaltonSequence test = new HaltonSequence(base);
		for(int x = 0; x < 100; x++){
			double[] t = test.getNext();
			System.out.println(t[0] + "\t" + t[1]);
		}
		
	}
}</span>



版权声明:本文为博主原创文章,未经博主允许不得转载。

Halton Sequence 原理和代码实现

标签:mapreduce   算法   halton   sequence   随机   

原文地址:http://blog.csdn.net/amber_amber/article/details/47421053

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!