How do I create a list of random numbers without duplicates?

前端 未结 17 2406
灰色年华
灰色年华 2020-11-22 13:30

I tried using random.randint(0, 100), but some numbers were the same. Is there a method/module to create a list unique random numbers?

Note: The fol

17条回答
  •  执念已碎
    2020-11-22 13:37

    Linear Congruential Pseudo-random Number Generator

    O(1) Memory

    O(k) Operations

    This problem can be solved with a simple Linear Congruential Generator. This requires constant memory overhead (8 integers) and at most 2*(sequence length) computations.

    All other solutions use more memory and more compute! If you only need a few random sequences, this method will be significantly cheaper. For ranges of size N, if you want to generate on the order of N unique k-sequences or more, I recommend the accepted solution using the builtin methods random.sample(range(N),k) as this has been optimized in python for speed.

    Code

    # Return a randomized "range" using a Linear Congruential Generator
    # to produce the number sequence. Parameters are the same as for 
    # python builtin "range".
    #   Memory  -- storage for 8 integers, regardless of parameters.
    #   Compute -- at most 2*"maximum" steps required to generate sequence.
    #
    def random_range(start, stop=None, step=None):
        import random, math
        # Set a default values the same way "range" does.
        if (stop == None): start, stop = 0, start
        if (step == None): step = 1
        # Use a mapping to convert a standard range into the desired range.
        mapping = lambda i: (i*step) + start
        # Compute the number of numbers in this range.
        maximum = (stop - start) // step
        # Seed range with a random integer.
        value = random.randint(0,maximum)
        # 
        # Construct an offset, multiplier, and modulus for a linear
        # congruential generator. These generators are cyclic and
        # non-repeating when they maintain the properties:
        # 
        #   1) "modulus" and "offset" are relatively prime.
        #   2) ["multiplier" - 1] is divisible by all prime factors of "modulus".
        #   3) ["multiplier" - 1] is divisible by 4 if "modulus" is divisible by 4.
        # 
        offset = random.randint(0,maximum) * 2 + 1      # Pick a random odd-valued offset.
        multiplier = 4*(maximum//4) + 1                 # Pick a multiplier 1 greater than a multiple of 4.
        modulus = int(2**math.ceil(math.log2(maximum))) # Pick a modulus just big enough to generate all numbers (power of 2).
        # Track how many random numbers have been returned.
        found = 0
        while found < maximum:
            # If this is a valid value, yield it in generator fashion.
            if value < maximum:
                found += 1
                yield mapping(value)
            # Calculate the next value in the sequence.
            value = (value*multiplier + offset) % modulus
    

    Usage

    The usage of this function "random_range" is the same as for any generator (like "range"). An example:

    # Show off random range.
    print()
    for v in range(3,6):
        v = 2**v
        l = list(random_range(v))
        print("Need",v,"found",len(set(l)),"(min,max)",(min(l),max(l)))
        print("",l)
        print()
    

    Sample Results

    Required 8 cycles to generate a sequence of 8 values.
    Need 8 found 8 (min,max) (0, 7)
     [1, 0, 7, 6, 5, 4, 3, 2]
    
    Required 16 cycles to generate a sequence of 9 values.
    Need 9 found 9 (min,max) (0, 8)
     [3, 5, 8, 7, 2, 6, 0, 1, 4]
    
    Required 16 cycles to generate a sequence of 16 values.
    Need 16 found 16 (min,max) (0, 15)
     [5, 14, 11, 8, 3, 2, 13, 1, 0, 6, 9, 4, 7, 12, 10, 15]
    
    Required 32 cycles to generate a sequence of 17 values.
    Need 17 found 17 (min,max) (0, 16)
     [12, 6, 16, 15, 10, 3, 14, 5, 11, 13, 0, 1, 4, 8, 7, 2, ...]
    
    Required 32 cycles to generate a sequence of 32 values.
    Need 32 found 32 (min,max) (0, 31)
     [19, 15, 1, 6, 10, 7, 0, 28, 23, 24, 31, 17, 22, 20, 9, ...]
    
    Required 64 cycles to generate a sequence of 33 values.
    Need 33 found 33 (min,max) (0, 32)
     [11, 13, 0, 8, 2, 9, 27, 6, 29, 16, 15, 10, 3, 14, 5, 24, ...]
    

提交回复
热议问题