簡體   English   中英

為兩個數字的組合生成唯一值

[英]Generate a unique value for a combination of two numbers

考慮我有兩個數字1023232和44.我想生成一個代表這個數字組合的唯一數字。 我該如何生成它?

需求

f(x,y)= f(y,x)和f(x,y)對於每個(x,y)或(y,x)是唯一的

如果這是兩個整數,你可以這樣做:

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

如果需要為給定大小的兩個變量生成一個真正唯一的值,則需要大約每個變量大小的兩倍。 (好吧,現在f(x,y)== f(y,x)有點少)

您也可以通過反轉相同的操作來恢復原始值。

你可以使用這里給出功能 這是我見過的最節省空間的,也不涉及任何字符串方法。 但鏈接中的本機函數不適用於負整數。 但您可以按如下所示對其進行修改,使其適用於負整數。

這也會給出負面結果。 有關它和其他選項的更多信息, 請參閱此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;
}

使用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”

結果= 1023232202440

要對此進行解碼,您只需要提取字符串表示的最后一位( encoded ),然后使用對Convert.ToInt32(Substring)兩次調用將其他數字轉換回int

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

要處理否定 - 由於數字<= 10,你可以在最后一位數字中再添加兩個數據位來存儲每個int的符號 - 1表示正數,0表示負數。 另外 - 如果兩個int都非常大, result將不適合Int64 ,你必須使用System.Numerics BigInteger

如果你正在使用整數並且不介意結果很長,那么這應該有效:

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

數字存儲在結果的高和低雙字中這一事實可以獲得您的唯一性約束。

事實上,較高的數字總是在高dword中獲得你想要的對稱性。

Botz3000提供“正確”的解決方案。 我只想補充一點:要解決問題,您必須知道每個數字的最大可能大小,並且可接受的結果必須是兩個數字大小的總和。 即如果Botz3000假設每個數字保證適合32位,那么結果將需要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相同。

首先你要知道你不能將兩個int.MaxValue中的uniq值設置為一個int,而@ Botz3000的答案不會從F(1,2)和F(2,1)中產生uniq值,所以你可以使用這個方法:

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

這將適用於任何事情,您可以將結果和參數更改為short,ushort,int,uint或ulong的結果,因為它使用bytes.you只需要根據需要更改BitConverter方法。

獲取較小值的示例(從兩個小的int得到小的長):

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

如果你可以把它表示為一個字符串,這應該工作:

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

您可以將這兩個數字組合成一個字符串,並使用SHA1生成基於該字符串的哈希。

如果X和Y是Int,請添加一個分隔符。 永遠獨一無二

X = 100,Y = 5 => 100.5

X = 1023232,Y = 44 => 1023232.44

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM