考虑我有两个号码1023232&我想生成一个代表这个数字组合的唯一数字。我怎样才能产生它?
要求
f(x,y)= f(y,x)和f(x,y)对于每个(x,y)或(y,x)
是唯一的答案 0 :(得分:12)
如果这是两个整数,你可以这样做:
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))
您也可以通过撤消相同的操作来恢复原始值。
答案 1 :(得分:1)
使用Int32
作为字符串的长度为&lt; = 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
),然后使用两次调用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
s存储一个符号 - 1表示正数,0表示负数。另外,如果result
的{{1}}非常大,则Int64
将不适合int
,您必须使用BigInteger
中的System.Numerics
答案 2 :(得分:1)
如果你正在使用整数并且不介意结果很长,那么这应该有效:
Math.Max(x, y) << 32 | Math.Min(x, y)
数字存储在结果的高和低双字中这一事实可以获得你的唯一性约束。
更高的数字总是在高dword中这一事实可以获得你想要的对称性。
答案 3 :(得分:1)
您可以使用function given here。这是我见过的最节省空间的,也不涉及任何字符串方法。但链接中的本机函数不适用于负整数。但您可以按如下所示对其进行修改,使其适用于负整数。
这也会给出负面结果。有关它和其他选项的更多信息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;
}
答案 4 :(得分:0)
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相同。
答案 5 :(得分:0)
首先你必须知道你不能将两个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);
}
答案 6 :(得分:-1)
如果您可以将其表示为字符串,则应该可以使用:
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 :(得分:-1)
您可以将这两个数字组合成一个字符串,并使用SHA1生成基于该字符串的哈希值。
答案 8 :(得分:-1)
如果X&amp; Y是Int添加一个分隔符。永远是独一无二的。
X = 100,Y = 5 =&gt; 100.5
X = 1023232,Y = 44 =&gt; 1023232.44