[英]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.