Creating random numbers with no duplicates

后端 未结 18 1805
忘了有多久
忘了有多久 2020-11-21 12:00

In this case, the MAX is only 5, so I could check the duplicates one by one, but how could I do this in a simpler way? For example, what if the MAX has a value of 20? Thanks

18条回答
  •  挽巷
    挽巷 (楼主)
    2020-11-21 12:08

    There is another way of doing "random" ordered numbers with LFSR, take a look at:

    http://en.wikipedia.org/wiki/Linear_feedback_shift_register

    with this technique you can achieve the ordered random number by index and making sure the values are not duplicated.

    But these are not TRUE random numbers because the random generation is deterministic.

    But depending your case you can use this technique reducing the amount of processing on random number generation when using shuffling.

    Here a LFSR algorithm in java, (I took it somewhere I don't remeber):

    public final class LFSR {
        private static final int M = 15;
    
        // hard-coded for 15-bits
        private static final int[] TAPS = {14, 15};
    
        private final boolean[] bits = new boolean[M + 1];
    
        public LFSR() {
            this((int)System.currentTimeMillis());
        }
    
        public LFSR(int seed) {
            for(int i = 0; i < M; i++) {
                bits[i] = (((1 << i) & seed) >>> i) == 1;
            }
        }
    
        /* generate a random int uniformly on the interval [-2^31 + 1, 2^31 - 1] */
        public short nextShort() {
            //printBits();
    
            // calculate the integer value from the registers
            short next = 0;
            for(int i = 0; i < M; i++) {
                next |= (bits[i] ? 1 : 0) << i;
            }
    
            // allow for zero without allowing for -2^31
            if (next < 0) next++;
    
            // calculate the last register from all the preceding
            bits[M] = false;
            for(int i = 0; i < TAPS.length; i++) {
                bits[M] ^= bits[M - TAPS[i]];
            }
    
            // shift all the registers
            for(int i = 0; i < M; i++) {
                bits[i] = bits[i + 1];
            }
    
            return next;
        }
    
        /** returns random double uniformly over [0, 1) */
        public double nextDouble() {
            return ((nextShort() / (Integer.MAX_VALUE + 1.0)) + 1.0) / 2.0;
        }
    
        /** returns random boolean */
        public boolean nextBoolean() {
            return nextShort() >= 0;
        }
    
        public void printBits() {
            System.out.print(bits[M] ? 1 : 0);
            System.out.print(" -> ");
            for(int i = M - 1; i >= 0; i--) {
                System.out.print(bits[i] ? 1 : 0);
            }
            System.out.println();
        }
    
    
        public static void main(String[] args) {
            LFSR rng = new LFSR();
            Vector vec = new Vector();
            for(int i = 0; i <= 32766; i++) {
                short next = rng.nextShort();
                // just testing/asserting to make 
                // sure the number doesn't repeat on a given list
                if (vec.contains(next))
                    throw new RuntimeException("Index repeat: " + i);
                vec.add(next);
                System.out.println(next);
            }
        }
    }
    

提交回复
热议问题