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

一个小问题引发的思考

时间:2015-08-04 10:41:24      阅读:129      评论:0      收藏:0      [点我收藏+]

标签:

一个小问题引发的思考

随机生成20个不重复A-Z的字符串,并且顺序排列

题目挺简单要注意几个点,一 :A-Z的生成 二 : 随机数 三  :不重复,  顺序排列

A-Z的生成:利用ascii码表生成字母  //确定A-Z的   ascii码表   (65-90)  

i=65
char c=(char) i;//c即为"A"

 

再利用随机数生成 不同的字符串   

 int i=new Random().nextInt(26)+65;

20个不重复的,循环确定个数,set保存不重复的对象集合

	while(true){
	    int i=new Random().nextInt(26)+65;
	       char c=(char) i;
	       if(set.size()<=20){
	    	   set.add(c);
	       }
	       else{
	    	   break;
	       }
		}

 最后一步:顺序保存,只需要set集合使用treeSet就可,treeSet是根据对象实现comparable接口按顺序保存对象。

完整例子

public static void main(String[] args) {
        //确定A-Z的   ascii码表   (65-90)
        TreeSet<Character> set =new TreeSet<Character>();
        while(true){
        int i=new Random().nextInt(26)+65;
           char c=(char) i;
           if(set.size()<=20){
               set.add(c);
           }
           else{
               break;
           }
        }
        
        for(Iterator<Character> i=set.iterator();i.hasNext();){
              char c=  i.next();
              System.out.println(c);
        }
    }

 

上述只是一个很简单的小问题,但有两个问题可以深入探讨下

一:随机数 

java生成的随机数是伪随机数,即不是真正的随机,只是按照一定的规则模拟出来的。

java中生成随机数有两种方法   一种就是开始上面实现的随机数    int i=new Random().nextInt(26) 生成一个0-25的实际整数    

 另一种则是  Math.random()    生成一个0-1的浮点数

这两种的区别

先看  Math.random() 的源码

 private static Random randomNumberGenerator;

    private static synchronized Random initRNG() {
        Random rnd = randomNumberGenerator;
        return (rnd == null) ? (randomNumberGenerator = new Random()) : rnd;
    }


  public static double random() {
        Random rnd = randomNumberGenerator;
        if (rnd == null) rnd = initRNG();
        return rnd.nextDouble();
    }

简单的说,Math.random() 还是调用了 random对象的 nextDouble()方法,只不过random对象是静态的,单一的,上锁的random对象

接下来看  nextDouble()方法,nextDouble()调用了next()方法,值得说下的是,nextInt()方法之调用了一次next(),速度会比nextDouble()快一丢丢

 public double nextDouble() {
        return (((long)(next(26)) << 27) + next(27))
            / (double)(1L << 53);
    }

 接下来继续看next()方法, next()中有一个很重要的属性  oldseed,所有运算结果都是根据它生成,而oldseed是怎么生成的

 protected int next(int bits) {
        long oldseed, nextseed;
        AtomicLong seed = this.seed;
        do {
            oldseed = seed.get();
            nextseed = (oldseed * multiplier + addend) & mask;
        } while (!seed.compareAndSet(oldseed, nextseed));
        return (int)(nextseed >>> (48 - bits));
    }

 

又下面可以知道.oldseed是由几个常数 加系统时间来运算确定的 ,所以呢java随机数不是真随机只是个伪随机,并且不是很安全,因为很容易被算是随机值,但是可以用java.security.SecureRandom,这个更安全,因为重写了next()方法。

 public Random() {
        this(seedUniquifier() ^ System.nanoTime());
    }

    private static long seedUniquifier() {
        // L‘Ecuyer, "Tables of Linear Congruential Generators of
        // Different Sizes and Good Lattice Structure", 1999
        for (;;) {
            long current = seedUniquifier.get();
            long next = current * 181783497276652981L;
            if (seedUniquifier.compareAndSet(current, next))
                return next;
        }
    }

    private static final AtomicLong seedUniquifier
        = new AtomicLong(8682522807148012L);

 

最后:http://blog.csdn.net/ultrani/article/details/7818082 这边博文的作者写的更清晰,也更深入的说明random函数算法的原理,有兴趣可以去看下

 

 

 

 

 

 

 

 

 

 

 

 

 

 

一个小问题引发的思考

标签:

原文地址:http://www.cnblogs.com/qiuyuedong/p/4699767.html

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