`

在Android开发中用到的MT随机数生成器

 
阅读更多

把以前的AS3移植版略改了一下,目前正用在jkanji中。测试过一段时间,貌似没什么bug。做过一个最简单的硬币测试,在相同种子的情况下正反面次数是差不多。不过以前看过一本书说MT算法不是最好的,而且网上有很多实现,我只是让它的计算结果尽可能接近于原来的C版本。

官网介绍在:

Mersenne Twister Home Page

http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html

 

实现和测试代码在同一个类中,见下:

 

package com.iteye.weimingtom.jkanji;

/**
 * Mersenne Twister with improved initialization (2002)
 * @see http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/mt19937ar.html
 * @see http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.c
 * 
 * changed:
 * 		1. init_genrand: mt[mti], add temp
 * 		2. >>: >>>
 * 		3. uint => int
 * 		4. long genrand_int32()
 * 		5. y & 0xffffffffL
 */
public class MersenneTwisterRandom {
	private static final int N = 624;
	private static final int M = 397;
	private static final int MATRIX_A = 0x9908b0df;
	private static final int UPPER_MASK = 0x80000000;
	private static final int LOWER_MASK = 0x7fffffff;
	private int[] mt = new int[N];
	private int mti = N + 1;
	
	public void init_genrand(int s) {
		mt[0] = s & 0xffffffff;
		for (mti = 1; mti < N; mti++) {
			int temp = (1812433253 * (mt[mti - 1] ^ (mt[mti - 1] >>> 30))) & 0xFFFFFFFF;
			mt[mti] = temp + mti;
			mt[mti] &= 0xffffffff;
		}
	}
	
	public void init_by_array(int[] init_key, int key_length) {
		int i, j, k;
		init_genrand(19650218);
		i = 1;
		j = 0;
		k = (N > key_length ? N : key_length);
		for (; k != 0; k--) {
			mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >>> 30)) * 1664525)) + init_key[j] + j;
			mt[i] &= 0xffffffff;
			i++; 
			j++;
			if (i >= N) { 
				mt[0] = mt[N - 1]; 
				i = 1; 
			}
			if (j >= key_length) {
				j = 0;
			}
		}
		for (k = N - 1; k != 0; k--) {
			mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >>> 30)) * 1566083941)) - i;
			mt[i] &= 0xffffffff;
			i++;
			if (i >= N) { 
				mt[0] = mt[N - 1];
				i = 1; 
			}
		}
		mt[0] = 0x80000000;
	}
	
	public long genrand_int32() {
		int y;
		int[] mag01 = {0x0, MATRIX_A};
		if (mti >= N) {
			int kk;	
			if (mti == N + 1) {
				init_genrand(5489);
			}
			for (kk = 0; kk < N - M; kk++) {
				y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
				mt[kk] = mt[kk + M] ^ (y >>> 1) ^ mag01[y & 0x1];
			}
			for (; kk < N - 1; kk++) {
				y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
				mt[kk] = mt[kk + (M - N)] ^ (y >>> 1) ^ mag01[y & 0x1];
			}
			y = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
			mt[N - 1] = mt[M - 1] ^ (y >>> 1) ^ mag01[y & 0x1];
			mti = 0;
		}
		y = mt[mti++];
		y ^= (y >>> 11);
		y ^= (y << 7) & 0x9d2c5680;
		y ^= (y << 15) & 0xefc60000;
		y ^= (y >>> 18);
		return y & 0xffffffffL;
	}
	
	public int genrand_int31() {
		return (int)(genrand_int32() >> 1);
	}
	
	public double genrand_real1() {
		return genrand_int32() * (1.0 / 4294967295.0); 
	}
	
	public double genrand_real2() {
		return genrand_int32() * (1.0 / 4294967296.0);
	}
	
	public double genrand_real3() {
		return ((double)(genrand_int32()) + 0.5) * (1.0 / 4294967296.0);
	}
	
	public double genrand_res53() { 
		long a = genrand_int32() >>> 5, b = genrand_int32() >>> 6;
		return(a * 67108864.0 + b) * (1.0 / 9007199254740992.0);
	}
	
	public MersenneTwisterRandom() {
		
	}
	
    public int nextInt(int min, int max) {
        return min + (int)Math.floor(genrand_real2() * (max - min + 1));
    }
	
	public static final void main(String[] args) {
		{
			String strTrace = "";
			int i;
			int[] init = {0x123, 0x234, 0x345, 0x456};
			MersenneTwisterRandom random = new MersenneTwisterRandom();
			random.init_by_array(init, init.length);
			strTrace += "1000 outputs of genrand_int32()\n";
			for (i = 0; i < 1000; i++) {
				strTrace += random.genrand_int32() + " ";
				if (i % 5 == 4) {
					strTrace += "\n";
				}
			}
			strTrace += "\n1000 outputs of genrand_real2()\n";
			for (i = 0; i < 1000; i++) {
				strTrace += random.genrand_real2() + " ";
				if (i % 5 == 4) 
				{
					strTrace += "\n";
				}
			}
			System.out.println(strTrace);
		}
		{
			//coin test
			MersenneTwisterRandom mt = new MersenneTwisterRandom();
			mt.init_genrand((int)System.currentTimeMillis());
			int heads = 0;
			int tails = 0;
			for (int j = 1; j <= 1000000; j++) {
				int i = (int)Math.floor(mt.genrand_real2() * 2);
				if (i == 0) { 
					heads ++;
				} else { 
					tails ++;
				}
			}
			System.out.println("heads = " + heads);
			System.out.println("tails = " + tails);
		}
	}
}

 

注意,我不能保证它的运行结果是正确的。

通常我喜欢像这样取一个整数范围内的随机整数:

 

		MersenneTwisterRandom mt = new MersenneTwisterRandom();
		mt.init_genrand((int)System.currentTimeMillis());
		int total = getCount(context);
		int id = mt.nextInt(0, total - 1);
 

 

 

分享到:
评论

相关推荐

    随机数生成器源码

    随机数生成器是计算机科学中的一个重要工具,广泛应用于各种领域,如模拟仿真、加密算法、游戏开发、统计分析等。本资源提供了一个随机数生成器的源码以及打包好的软件,用户可以根据自己的需求生成指定区间内的任意...

    0-100随机数生成器

    总的来说,"0-100随机数生成器"是一个使用JAVA编写的、可以在无JAVA环境的机器上运行的工具,它利用了JAVA的`Random`类或其他随机数生成机制,可能包含用户友好的界面和/或定制的随机数算法。对于那些需要在多种环境...

    随机数生成器

    随机数生成器是一种在计算机程序中...总之,随机数生成器是一个涵盖广泛技术的领域,从基础的数学算法到复杂的加密原理,都在其中有所体现。理解其工作原理和应用可以帮助我们更好地利用这一工具服务于各种实际需求。

    Linux随机数生成器的原理及缺陷.pdf

    在设计随机数生成器时,需要考虑到安全性和性能之间的平衡。随机数生成器的安全性取决于熵值的收集和处理,而性能取决于随机数生成的速度和效率。因此,需要设计出一个高效、安全的随机数生成器来满足系统的需求。 ...

    sp800_90c_second_draft.pdf 随机数生成器标准 NIST

    信息安全专家、系统架构师、密码学家以及其他相关专业人士会根据该标准设计、开发、测试、部署随机数生成器,以满足当前信息安全领域的需求。同时,NIST SP 800-90系列标准的更新还会根据新的研究结果和技术进步而...

    随机段小数生成器1_区间随机数生成器_

    在IT领域,随机数生成器是一种非常重要的工具,特别是在模拟、加密、统计分析以及游戏开发等众多应用中。"随机段小数生成器1_区间随机数生成器_"的标题和描述暗示了这是一个软件或算法,它允许用户指定一个特定的...

    java随机数生成器

    可以生成制定范围内的随机数。有GUI界面

    随机数生成器(hex)

    随机数生成器是编程中非常常见的一种工具,它在各种领域都有应用,如加密、模拟、游戏、测试等。在本例中,我们讨论的是一个特定的随机数生成器,它能够生成指定数量的随机数,并将这些数字保存为文本文件“randrom....

    用C++写的随机数生成器(含源代码)

    在本文中,我们将深入探讨如何使用C++编程语言创建一个随机数生成器。这个生成器允许用户指定随机数的范围和需要生成的个数。在C++中,生成随机数是一项基本任务,常用于各种应用,如模拟、游戏、测试等。 首先,...

    随机数生成器(源码)

    在编程领域,随机数生成器是一种至关重要的工具,特别是在模拟、加密、游戏开发以及各种统计计算中。VB(Visual Basic)作为经典的编程语言,虽然内置了`Rnd`函数用于生成随机数,但在某些情况下,它可能无法满足...

    随机数生成器在Android设备上的应用.pdf

    《随机数生成器在Android设备上的应用》 随机数生成器是计算机科学中不可或缺的工具,尤其在Android设备上,由于其广泛的应用场景,如统计分析、加密算法、游戏设计和抽奖程序等,对随机数生成的需求日益增长。然而...

    C 代码 实现具有拆分功能的随机数生成器 (RNG), 允许计算多个独立的流.rar

    随机数生成器在各种科学计算、模拟、游戏开发以及加密算法中都有着广泛的应用。一个支持拆分功能的RNG允许我们生成多个独立的随机数序列,这对于并行计算或需要复现特定随机过程的场景特别有用。 首先,我们来看看`...

    随机数生成器-Python编写

    在编程领域,随机数生成器是一种非常重要的工具,特别是在模拟、加密、游戏开发以及数据分析等多个领域。Python作为一门广泛使用的编程语言,内置了强大的随机数模块`random`,使得开发者可以方便地生成各种类型的...

    Winform-随机数生成器

    在这个"Winform-随机数生成器"项目中,我们关注的核心是利用编程技术来生成各种类型的随机数,包括序列号、纯数字以及字符串。这个工具的灵活性在于用户能够自定义生成纯数字时的位数,以满足不同场景的需求。 首先...

    随机数生成器(包括数字、字母、特殊符号)

    随机数生成器(包括数字、字母、特殊符号)

    BAT批处理学习-数值计算-random随机数生成器.zip

    本文将深入探讨“BAT批处理学习-数值计算-random随机数生成器.zip”这个主题,以及如何在批处理脚本中创建随机数生成器。 批处理脚本是基于DOS命令行环境的文本文件,它包含了多个操作系统命令,通过运行这些命令来...

    0-999随机数_quartus随机数_vhdl_随机数生成器_随机数电路_随机数_

    1. 设计并实现一个随机数生成电路,每2秒随机生成一个0~999之间的数字,并在数码管上显示生成的随机数。2. 为系统设置一个复位键,复位后数码管显示“000”,2秒后再开始每2秒生成并显示随机数,要求使用按键复位。

Global site tag (gtag.js) - Google Analytics