Java随机数
来源:互联网 发布:数据库题库和答案2016 编辑:程序博客网 时间:2024/06/05 14:13
为什么说Java中的随机数都是伪随机数?
什么是伪随机数?
1.伪随机数是看似随机实质是固定的周期性序列,也就是有规则的随机。
2.只要这个随机数是由确定算法生成的,那就是伪随机,只能通过不断算法优化,使你的随机数更接近随机。
(随机这个属性和算法本身就是矛盾的)
3.通过真实随机事件取得的随机数才是真随机数。
Java随机数产生方式:
1,使用Math.random()方法来产生一个随机数,这个产生的随机数是0-1之间的一个double,我们可以把他乘以一定的数,比如说乘以100,他就是个100以内的随机。
System.out.println(Math.random());
2,在java.util这个包里面提供了一个Random的类,我们可以新建一个Random的对象来产生随机数,他可以产生随机整数、随机float、随机double,随机long。
Random random=new Random(); System.out.println(random.nextInt(1000)); System.out.println(random.nextDouble());
3,在我们的System类中有一个currentTimeMillis()方法,这个方法返回一个从1970年1月1号0点0分0秒到目前的一个毫秒数,返回类型是long,我们可以拿他作为一个随机数,我们可以拿他对一些数取模,就可以取得随机数,类似的System类还有nanoTime()方法,返回纳秒级时间。
System.out.println(System.currentTimeMillis()); System.out.println(System.nanoTime());
需要说明的是:
java.Math.Random()实际是在内部调用java.util.Random()的:
以下Math.class的源码,可见Math是基于一个java.util.Random单例的。
public static double random() { return RandomNumberGeneratorHolder.randomNumberGenerator.nextDouble(); }
private static final class RandomNumberGeneratorHolder { static final Random randomNumberGenerator = new Random(); }
Random有两种构造方法:
Random():使用一个和当前系统时间对应的相对时间有关的数字作为种子数。
Random(long seed):直接传入一个种子数。
种子的作用是什么?
种子就是产生随机数的第一次使用值,机制是通过一个函数,将这个种子的值转化为随机数空间中的某一个点上,并且产生的随机数均匀的散布在空间中。以后产生的随机数都与前一个随机数有关。
举例:
Random r1 = new Random(); Random r2 = new Random(); //无参构造使用的是参数作为种子数 Random r3 = new Random(100); Random r4 = new Random(100); //产生随机数调用nextXXX()方法 System.out.println(r1.nextInt(10)); System.out.println(r1.nextInt(10)); System.out.println(r2.nextInt(10)); System.out.println(r2.nextInt(10)); System.out.println("-----------------"); System.out.println(r3.nextInt(10)); System.out.println(r3.nextInt(10)); System.out.println(r4.nextInt(10)); System.out.println(r4.nextInt(10));
结果:
5140-----------------5050
r3,r4产生的随机数序列是相同的。
Java自带的随机数函数是很容易被黑客破解的,因为黑客可以通过获取一定长度的随机数序列来推出你的seed,然后就可以预测下一个随机数。程序员可以自己编写随机数生成算法并不断优化,安全性会得到提高。
这里给出一个自编的随机数生成方法:
static double rand(double[] seed){//注意传入参数是一个数组类型 double base=256.0; double u=16.0; double v=123.2; double temp1,temp2,temp3; temp1=u*seed[0]+v; temp2=(int)(temp1/base); temp3=temp1-temp2*base; seed[0]=temp3; double random=seed[0]/base; return random; }
public static void main(String[] args) { double[] seed={5.0};//必须使用数组传入,因为必须要传地址,才能改变在内存中的值,如果只传入一个double类型,生成出来将始终是一个数 System.out.println(rand(seed)); System.out.println(rand(seed)); System.out.println(rand(seed)); System.out.println(rand(seed)); }
无论是JDK带有的随机数方法还是程序员自己编写的随机数方法,都是通过一个或简单或复杂的算法生成的。因此都是伪随机数,都具有不安全性。因此从这个意义,随机数可以分为一般随机数,逼真随机数和真实随机数。理论上计算机编程是不可能实现真实随机数的。我们能做的只有尽可能的逼真。
例如,使用每次生成随机数,使用系统时间作为seed,就可以相对简单地构建一个不易破解的随机数生成器。
public static int closeRand(int totalNum){ int random; Random randomGenerator=new Random(System.nanoTime()); random=randomGenerator.nextInt(totalNum); return random; }
再比如JDK还提供了java.security.SecurityRandom类,它继承了java.util.Random类但重写了生成方法,可以产生强随机数:
static int secureRand(int n) { final int offset = 123456; // offset为固定值,避免被猜到种子来源(和密码学中的加salt有点类似) long seed = System.currentTimeMillis() + offset; SecureRandom sr; try { sr = SecureRandom.getInstance("SHA1PRNG"); sr.setSeed(seed); return sr.nextInt(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return 0; }
毫无疑问,在降低效率的代价下提升了安全性。
参考资料:
http://www.cnblogs.com/greatfish/p/5845924.html
http://www.iteye.com/topic/872860
http://blog.csdn.net/ultrani/article/details/7818082
- java随机数
- Java随机数
- JAVA 随机数
- Java随机数
- java随机数
- JAVA 随机数
- Java随机数
- java 随机数
- java 随机数
- [java]随机数
- java随机数
- Java 随机数
- Java 随机数
- JAVA随机数
- JAVA随机数
- java 随机数
- Java随机数
- Java - 随机数
- 同用的网站登陆界面
- sql 查询时异常为明确定义的列
- MySQL的SQL语句写法
- 原生js轮播图
- 如何在星巴克点一杯好喝的咖啡
- Java随机数
- 关于stack 以及相关的寄存器的知识(x86 结构)
- 《嵌入式Linux应用程序开发详解》PDF完整版及源代码
- 反射、反射加壳、反射脱壳、反射注册机
- 开发细节,持续更新...
- URI模板
- php中不借助第三方交换两个变量的值
- 【ArcGIS Add-in编程】导入jpg等栅格数据、导入shapefile等矢量数据
- 快牙网传