Подтвердить что ты не робот

Создайте уникальное значение для комбинации двух чисел

У меня есть два номера 1023232 и 44. Я хочу сгенерировать уникальный номер, представляющий эту комбинацию чисел. Как я могу его создать?

Требование

f (x, y) = f (y, x) и f (x, y) единственно для каждого (x, y) или (y, x)

4b9b3361

Ответ 1

Если это два int, вы можете просто сделать это:

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

если вам нужно создать поистине уникальное значение для двух переменных заданного размера, вам нужно примерно удвоить размер каждой переменной. (ok, немного меньше теперь, когда f (x, y) == f (y, x))

Вы также можете вернуть свои исходные значения, изменив одну и ту же операцию.

Ответ 2

Используйте тот факт, что длина Int32 в качестве строки равна <= 10, сохраняет длину первого строкового представления int по модулю 10 в качестве последней цифры 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

Чтобы декодировать это, вам просто нужно извлечь последнюю цифру строкового представления (encoded), а затем преобразовать другие цифры обратно в int, используя два вызова 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));

Для обработки негативов - С# из цифр = lt; = 10 вы можете добавить еще два бита данных в последнюю цифру, чтобы сохранить знак для каждого из ваших int - 1 для положительных, 0 для отрицательных. Кроме того, result не будет вписываться в Int64, если оба ваших int очень велики, вам нужно будет использовать BigInteger из System.Numerics

Ответ 3

Если вы используете ints и не возражаете, чтобы результат был длинным, это должно работать:

Math.Max(x, y) << 32 | Math.Min(x, y)

Тот факт, что числа хранятся в высоком и низком словах результата, дает вам ограничение на уникальность.

Тот факт, что большее число всегда находится в высоком dword, получает вам симметрию, которую вы хотели.

Ответ 4

Вы можете использовать функцию указанную здесь. Это наиболее эффективное пространство, которое я видел, а также не требует каких-либо строковых подходов. Однако нативная функция в ссылке не работает для отрицательных целых чисел. Но вы можете изменить его, как показано ниже, чтобы заставить его работать с отрицательными целыми числами.

Это также даст отрицательные результаты. Подробнее об этом и других опциях см. Этот ответ SO.

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;
}

Ответ 5

Botz3000 дает "правильное" решение. Я бы просто добавил: Чтобы решить проблему, вы должны знать максимально возможный размер каждого числа, а приемлемый результат должен быть суммой размеров двух чисел. то есть, если каждый номер гарантированно будет соответствовать 32 битам, как предполагает Botz3000, тогда для результата потребуется 64 бита. Если это неприемлемо - если, скажем, у вас есть требование, чтобы на входе было два 32-битных номера, а выход должен соответствовать 32 битам - тогда проблема не разрешима, потому что не хватает возможных разных ответов.

Если это неясно, рассмотрим тривиальный случай: предположим, что входы каждый 1 бит, 0 или 1. Таким образом, для каждого числа есть два возможных значения, 2x2 = 4 возможных комбинаций. Поэтому ваш выход должен быть не менее 2 бит. Как вы говорите, f (x, y) = f (y, x), вы уменьшаете общее количество возможных ответов на коэффициент, несколько меньший 2. Опять же, в примере с 1 битом существует только 3 различных возможности: 0, 0; 0,1; и 1,1. 1,0 не является очевидной возможностью, так как она равна 0,1.

Ответ 6

Если вы можете представить его как строку, это должно работать:

Hash((int1 | int2).ToString());

Так же:

public static string Hash(string plaintext)
{
var hashAlgorithm = new SHA1CryptoServiceProvider();
var unhashedBuffer = Encoding.Default.GetBytes(plaintext);
var hashedBuffer = hashAlgorithm.ComputeHash(unhashedBuffer);
return Convert.ToBase64String(hashedBuffer);
)

Ответ 7

Вы можете объединить два числа в строку и создать хэш на основе этой строки, используя SHA1.

Ответ 8

Если X и Y - Int, добавьте разделитель. Всегда уникально.

X = 100, Y = 5 = > 100,5

X = 1023232, Y = 44 = > 1023232,44