Performance issue with generation of random unique numbers

前端 未结 10 658
星月不相逢
星月不相逢 2021-01-17 13:47

I have a situation where by I need to create tens of thousands of unique numbers. However these numbers must be 9 digits and cannot contain any 0\'s. My current approach is

10条回答
  •  醉酒成梦
    2021-01-17 14:27

    Try avoiding checks making sure that you always pick up a unique number:

    static char[] base9 = "123456789".ToCharArray();
    
    static string ConvertToBase9(int value) {
        int num = 9;
        char[] result = new char[9];
        for (int i = 8; i >= 0; --i) { 
            result[i] = base9[value % num];
            value = value / num;
        }
        return new string(result);
    }
    
    public static void generateIdentifiers(int quantity) {
        var uniqueIdentifiers = new List(quantity);
        // we have 387420489 (9^9) possible numbers of 9 digits in base 9.
        // if we choose a number that is prime to that we can easily get always
        // unique numbers
        Random random = new Random();
        int inc = 386000000;
        int seed = random.Next(0, 387420489);
        while (uniqueIdentifiers.Count < quantity) {
            uniqueIdentifiers.Add(ConvertToBase9(seed));
            seed += inc;
            seed %= 387420489;
        }
    }
    

    I'll try to explain the idea behind with small numbers...

    Suppose you have at most 7 possible combinations. We choose a number that is prime to 7, e.g. 3, and a random starting number, e.g. 4.

    At each round, we add 3 to our current number, and then we take the result modulo 7, so we get this sequence:

    4 -> 4 + 3 % 7 = 0
    0 -> 0 + 3 % 7 = 3
    3 -> 3 + 3 % 7 = 6
    6 -> 6 + 6 % 7 = 5

    In this way, we generate all the values from 0 to 6 in a non-consecutive way. In my example, we are doing the same, but we have 9^9 possible combinations, and as a number prime to that I choose 386000000 (you just have to avoid multiples of 3).

    Then, I pick up the number in the sequence and I convert it to base 9.

    I hope this is clear :)

    I tested it on my machine, and generating 400k unique values took ~ 1 second.

提交回复
热议问题