Generate a unique value for a combination of two numbers

后端 未结 9 850
有刺的猬
有刺的猬 2020-12-16 16:09

Consider I\'ve two numbers 1023232 & 44. I want to generate a unique number representing this combination of numbers. How can i generate it?

Requirement

相关标签:
9条回答
  • 2020-12-16 16:38

    You could use the function given here. This is the most space efficient I have seen and also doesn't involve any string approaches. The native function in the link won't work for negative integers though. But you can modify it as shown below to make it work for negative integers.

    This will give back negative results too. For more on it and other options see this SO answer.

    public static long GetHashCode_OrderIrrelevant(int a, int b)
    {
        return GetHashCode(Math.Min(a, b), Math.Max(a, b));
    }
    
    public static long GetHashCode(int a, int b)
    {
        var A = (ulong)(a >= 0 ? 2 * (long)a : -2 * (long)a - 1);
        var B = (ulong)(b >= 0 ? 2 * (long)b : -2 * (long)b - 1);
        var C = (long)((A >= B ? A * A + A + B : A + B * B) / 2);
        return a < 0 && b < 0 || a >= 0 && b >= 0 ? C : -C - 1;
    }
    
    0 讨论(0)
  • 2020-12-16 16:39

    if those are two ints, you could just do this:

    ulong F(int x, int y) {
        ulong id = x > y ? (uint)y | ((ulong)x << 32) :  
                           (uint)x | ((ulong)y << 32);
        return id;
    }
    

    if you need to generate a truly unique value for two variables of a given size, you need about double the size of each variable. (ok, a bit less now that f(x,y) == f(y,x))

    You could also get your original values back by reversing the same operation.

    0 讨论(0)
  • 2020-12-16 16:40

    Use the fact that length of Int32 as string is <= 10, store the length of the first int's string representation modulo 10 as the last digit of an Int64:

    int num1 = 1023232202;
    int num2 = 44;
    string encoded = num1.ToString() + num2.ToString() +  
        (num1.ToString().Length % 10).ToString();
    Int64 result = Convert.ToInt64(encoded);
    

    encoded = "1023232202440"

    result = 1023232202440

    To decode this you just need to extract the last digit of the string representation (encoded) and then convert the other digits back to int using two calls to Convert.ToInt32(Substring).

    encoded = result.ToString();
    int firstDigits = Convert.ToInt32(encoded[encoded.Length - 1] - '0');
    if (firstDigits == 0)
    {
        firstDigits = 10;
    }
    num1 = Convert.ToInt32(encoded.Substring(0, firstDigits));
    num2 = Convert.ToInt32(encoded.Substring(firstDigits, 
        encoded.Length - firstDigits - 1));
    

    To handle negatives - since # of digits <= 10, you could add two more data bits in the last digit to store a sign for each of your ints - 1 for positive, 0 for negative. Also - result won't fit in Int64 if both of your ints are very large, you would have to use BigInteger from System.Numerics

    0 讨论(0)
  • 2020-12-16 16:40

    Botz3000 gives the "correct" solution. I'd just add: To solve the problem, you must know the maximum possible size of each number, and an acceptable result must be the sum of the sizes of the two numbers. i.e. if each number is guaranteed to fit in 32 bits, as Botz3000 assumes, then the result will require 64 bits. If that is not acceptable -- if, say, you have a requirement that the input will be two 32 bit numbers and the output must fit in 32 bits -- then the problem is not solvable, because there aren't enough possible different answers.

    If that's not clear, consider a trivial case: suppose the inputs are each 1 bit, 0 or 1. So there are two possible values for each number, 2x2=4 possible combinations. Therefore your output must be at least 2 bits. As you say that f(x,y)=f(y,x), you reduce the total number of possible answers by a factor somewhat less than 2. Again, in the 1 bit example, there are only 3 distinct possibilities: 0,0; 0,1; and 1,1. 1,0 isn't a distinct possibility because it's the same as 0,1.

    0 讨论(0)
  • 2020-12-16 16:53

    You can combine the two numbers into a string, and generate a hash based on that string using SHA1.

    0 讨论(0)
  • 2020-12-16 16:54

    First you have to know you cannot make uniq value from two int.MaxValue to one int, and @Botz3000 answer don't make uniq value from F(1,2) and F(2,1) so you can use this method:

    public static long GetFixedCode(int x, int y)
    {
        return BitConverter.ToInt64(BitConverter.GetBytes(x).Concat(BitConverter.GetBytes(y)).ToArray(), 0);
    }
    

    This will work for anything and you can change result and parameters to short,ushort,int,uint, or result for ulong because its working with bytes.you need just change BitConverter method as you want to convert.

    Example for get smaller value (from two small int you will get small long):

     public static ulong GetFixedCode(uint x, uint y)
        {
            var array1 = BitConverter.GetBytes(x);
            var array2 = BitConverter.GetBytes(y);
            List<byte> resultArray = new List<byte>();
            resultArray.AddRange(array1.ToList().GetRange(0, 2));
            resultArray.AddRange(array2.ToList().GetRange(0, 2));
            resultArray.AddRange(array1.ToList().GetRange(2, 2));
            resultArray.AddRange(array2.ToList().GetRange(2, 2));
    
            return BitConverter.ToUInt64(resultArray.ToArray(), 0);
        }
    
    0 讨论(0)
提交回复
热议问题