不使用Math.random方法生成随机数(随机数生成器)
发布时间:2021-11-28 05:08:46
由于一些不可控因素的影响,比如系统内存,计算机状态等,每一次在while循环中执行的次数会有一定差异
大概几百次。这就导致了结果的差异。
注意这个程序使用了许多静态变量,也就是说,在下一个线程继续执行与上一个线程相同的run方法时,其初始值是上一个线程执行后的值,这形成了经典的蝴蝶效应,通过将这个差异放大,导致最终随机数的产生。
在这个程序中,一共开启了13个thread线程,每一次都会将那几个静态变量的值向混乱的方向推动,
于是最后得到的数组double[] bb的混乱程度几何上升,
最开始的bb[0]只有约几百个可能的值,而到了bb[3]就可以是65536个数据中的任何一个。
为了做到随机,我循环了13次,bb[12]几乎可以说是绝对的随机了。
/**
* Author:Yuanhonglong
* Date:2014-1-9
*/
public class MyRandom implements Runnable{
private static int random;
private static int f=127;
private static int m=(int)Math.pow(2,16);
private static int[] r=getR();
private static int x=13;
@Override
public void run(){
for(;!Thread.interrupted();){
f=((f/2)+r[f])%m;
random=r[f];
}
}
private static int[] getR(){
//将0-65536这65536个数按照一定顺序存入r[]中
int[] r=new int[m];
r[0]=13849;
for(int i=1;i<m;i++){
r[i]=((2053*r[i-1])+13849)%m;
}
int k=r[65535];
r[65535]=r[(f+1)%m];
r[(f+1)%m]=k;
return r;
}
private static void changeR(int[] r,int f){
//对r[]进行移动
int[] r1=new int[r.length];
System.arraycopy(r,0,r1,0,r.length);
for(int i=0;i<r.length;i++){
r[i]=r1[(i+f)%m];
}
}
public static double getRandom_0_1(){
double[] dd=new double[13];
for(int i=0;i<dd.length;i++){
Runnable runnable=new MyRandom();
Thread thread=new Thread(runnable);
thread.start();
try{
Thread.sleep(x+1);
}
catch(InterruptedException e){
e.getMessage();
}
thread.interrupt();
double rr=(double)random/(double)m;
x=f%13;
changeR(r,11+(f/7));
dd[i]=rr;
if((i>0)&&(dd[i]==dd[i-1])){
changeR(r,13+(f/11));
//防止不动点对程序的影响,当两个值相同说明程序有可能进入了死胡同,也就是不动点,关于不动点的问题可以参考高等数学关于函数的知识
}
}
double ran=dd[12];
return ran;
}
public static void main(String[] args){
double rs=getRandom_0_1();
System.out.println(rs);
}
}
MyRandom.java
/**
* Author:Yuanhonglong
* Date:2014-1-9
*/
package mine.loop;
public class MyRandom implements Runnable{
private static int random;
private static int f=127;
private static int m=(int)Math.pow(2,16);
private static int[] r=getR();
private static int x=13;
@Override
public void run(){
for(;!Thread.interrupted();){
f=((f/2)+r[f])%m;
random=r[f];
}
}
private static int[] getR(){
// 将0-65536这65536个数按照一定顺序存入r[]中
int[] r=new int[m];
r[0]=13849;
for(int i=1;i<m;i++){
r[i]=((2053*r[i-1])+13849)%m;
}
int k=r[65535];
r[65535]=r[(f+1)%m];
r[(f+1)%m]=k;
return r;
}
private static void changeR(int[] r,int f){
int[] r1=new int[r.length];
System.arraycopy(r,0,r1,0,r.length);
for(int i=0;i<r.length;i++){
r[i]=r1[(i+f)%m];
}
}
public static double getRandom_0_1(){
double[] dd=new double[13];
for(int i=0;i<dd.length;i++){
Runnable runnable=new MyRandom();
Thread thread=new Thread(runnable);
thread.start();
try{
Thread.sleep(x+1);
}
catch(InterruptedException e){
e.getMessage();
}
thread.interrupt();
double rr=(double)random/(double)m;
x=f%13;
changeR(r,11+(f/7));
dd[i]=rr;
if((i>0)&&(dd[i]==dd[i-1])){
changeR(r,13+(f/11));
// 防止不动点对程序的影响,当两个值相同说明程序有可能进入了死胡同,也就是不动点,关于不动点的问题可以参考高等数学关于函数的知识
}
}
double ran=dd[12];
return ran;
}
public static void main(String[] args){
double rs=getRandom_0_1();
System.out.println(rs);
}
}


猜你喜欢
- 刚刚看MSDN的一个例子无意发现的小技巧,大家一看就明白了,不过好像蛮有用的,先记下咯,以后慢慢研究。using System;namesp
- 关于java的字符串处理我们一般使用String类和StringBuffer类那么String类和StringBuffer类的区
- 背景先上图由此可见,非自旋锁如果拿不到锁会把线程阻塞,直到被唤醒;自旋锁拿不到锁会一直尝试为什么要这样?好处阻塞和唤醒线程都是需要高昂的开销
- java 在Jetty9中使用HttpSessionListener和FilterHttpSessionListener当Session创建
- 参考资料《Java 编程思想》,关于含有基类的导出类,其成员的初始化过程是一个容易让人困惑的地方,下面通过具体的实例进行讲解,代码取自《Ja
- 简单介绍华为鸿蒙系统应用开发工具 DevEco Studio的安装和使用据说12月份鸿蒙系统会推出手机的SDK哦,作为一名普通的开发者,表示
- 转拼音的依赖implementation 'com.github.SilenceDut:jpinyin:v1.0'FastI
- 老大让我check out 一个分支,可我在idea 右下角找了半天也没找到最后才发现:因为是刚创建的分支,我得先更新一下项目,连这个都不懂
- 前言本文主要给大家介绍了关于Spring4自定义@Value功能的相关内容,使用的Spring版本4.3.10.RELEASE,下面话不多说
- 需要装一个插件:File - Settings- Plugins - 搜索gson 安装GsonFromat;如下两张图安装完成后 ,新建一
- 什么是RestTemplate传统情况下在java代码里访问restful服务,一般使用Apache的HttpClient。不过
- dependencyManagement一般出现在最顶层父工程的pom文件中,它的作用是用来管理jar版本,让子项目引用一个依赖而不用指明版
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&
- 一个图片识别小工具,原先主要是识别以前公司的软件注册码截图里的数字和字母(每次要一个一个框复制出来粘贴到注册器里,很麻烦!),因为注册码出现
- 前言使用过SpringBoot的都应该知道,一个SpringBoot 项目就是由一个一个 Starter 组成的,一个 Starter 代表
- 在分布式系统架构中,如果一个应用不能对来自依赖的故障进行隔离,那该应用本身就处在被拖垮的风险中。 因此,为了构建稳定、可靠的分布式系统,我们
- 目录什么是Feign为什么使用Feign为什么要使用HTTP client为什么要使用Feign如何使用Feign项目环境说明引入依赖入门例
- 本文实例讲述了Android 开发使用PopupWindow实现加载等待界面功能。分享给大家供大家参考,具体如下:实现加载等待界面我用了两种
- 上一篇写了一下装箱拆箱的定义和IL分析,这一篇我们看下使用泛型和不使用泛型引发装箱拆箱的情况1.使用非泛型集合时引发的装箱和拆箱操作 看下面
- 线上出现了如上的 crash,第一解决反应是在 show dialog 之前做个 isFinish 和 isDestroyed 判断,当我翻