Verifying the uniqueness of a linear congruent generator for user identifiers

ID Requirements:

  • Short (# characters for user input)
  • Allow as many identifiers as possible
  • Seems random (so no one can easily guess the count of users by id)
  • No mixed code characters (easier for user)
  • No abusive words

So, I decided to go with an uppercase string with 6 characters, without vowels, created by a linear congruent generator ordered by user account. I learned about LCG from the wiki, and I would like to verify that my code is correct, since I myself compiled the coefficients in the LCG and would not want there to be a clash of identifiers. I myself tried to test for collisions, but I ran out of the heap of space while storing identifiers on the map after 2 million. I think that mathematics checks, but really appreciates the second (or thousand) set of eyes. (Also, this is actually not the case with JS, so if there is a more efficient way to replace vowels, I would like to know).

// UserId generated from stored userCount key in redis, sequenced by a Linear
// Congruental generator, and stringified with a radix of 31 (all numbers and
// letters besides vowels = 10 + 26 - 5 = 31).
//
// The equation we will use to generate the sequence is:
// userVal = (a * userCount + c) % m + minVal

// To guarantee each userId is at least 6 characters, we need:
// minVal = 31^5 = 28629151
//
// To guarantee that our userId is at most 6 characters, we need:
// log31(minVal + maxVal + 1) = 6
// => 31^6 = minVal + maxVal + 1
// => maxVal = 31^6 - minVal - 1 = 858874529
//
// So our LCG needs to have:
// 1) m < maxVal
// 2) m and c relatively prime
// 3) a-1 is divisible by 4 if m is
// 4) a-1 is divisible by all prime factors of m
//
// m = 858062848 = 2^16 * 13093
// c = 1
// a = 3351809 = 2^8 * 13093 + 1
//
// This means we can support 858062848 unique userIds (>850 million).
// If we ever cross that amount, it will be a good problem to solve :)
this.getUserId = function(){
    var userCount = Spark.getRedis().incr("unique-id:user");

    var a = 3351809;
    var c = 1;
    var m = 858062848;
    var minVal = 28629151;

    var userVal = (a * userCount + c) % m + minVal;

    return userVal.toString(31)
        .toUpperCase()
        .replace(/A/g, 'V')
        .replace(/E/g, 'W')
        .replace(/I/g, 'X')
        .replace(/O/g, 'Y')
        .replace(/U/g, 'Z');
};
Run codeHide result
+4
source share
1 answer

, , - , , , . , , . "" LCG, (, ), Numerical Recipes (Press et al.). Knuth Art of Computer Programming.

0

Source: https://habr.com/ru/post/1692346/


All Articles