为两个数字的组合生成唯一值

发布于 2024-10-03 00:57:22 字数 137 浏览 0 评论 0原文

假设我有两个号码 1023232 和 1023232。 44. 我想生成一个代表该数字组合的唯一数字。我怎样才能生成它?

要求

f(x,y) = f(y,x) 并且 f(x,y) 对于每个 (x,y) 或 (y,x) 都是唯一的

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

f(x,y) = f(y,x) and f(x,y) is unique for every (x,y) or (y,x)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

陈年往事 2024-10-10 00:57:22

如果它们是两个整数,您可以这样做:

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) 稍微少一点)

您也可以通过反转相同的操作来恢复原始值。

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.

苏辞 2024-10-10 00:57:22

如果您使用的是整数并且不介意结果很长,那么这应该可以工作:

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

数字存储在结果的高位和低位双字中,这一事实为您提供了唯一性约束。

事实上,较高的数字始终位于高位双字中,这可以让您获得所需的对称性。

If you are using ints and don't mind the result being a long, this should work:

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

The fact that the numbers are stored in the high and low dwords of the result get you your uniqueness constraint.

The fact that the higher number is always in the high dword gets you the symmetry you wanted.

似狗非友 2024-10-10 00:57:22

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

编码=“1023232202440”

结果=
1023232202440

要对此进行解码,您只需提取字符串表示形式的最后一位数字(encoded),然后使用两次 Convert 调用将其他数字转换回 int .ToInt32(子字符串)

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,则必须使用 BigInteger< /code> 来自 System.Numerics

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

冰之心 2024-10-10 00:57:22

您可以使用此处给出的函数。这是我见过的最节省空间的方法,而且不涉及任何字符串方法。不过,链接中的本机函数不适用于负整数。但您可以如下所示对其进行修改,使其适用于负整数。

这也会返回负面结果。有关它和其他选项的更多信息请参阅此答案。

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

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;
}
婴鹅 2024-10-10 00:57:22

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 相同。

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.

白昼 2024-10-10 00:57:22

首先,您必须知道您无法将 uniq 值从两个 int.MaxValue 转换为一个 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);
}

这适用于任何情况,您可以将结果和参数更改为短、ushort、int、uint 或 ulong 的结果,因为它与 bytes 一起使用。您只需根据需要更改 BitConverter 方法即可进行转换。

获取较小值的示例(从两个小 int 中,您将得到较小的 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);
    }

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);
    }
清引 2024-10-10 00:57:22

如果你可以将它表示为字符串,那么这应该可以工作:

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

If you can represent it as a string, this should work:

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

Like so:

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);
)
谁许谁一生繁华 2024-10-10 00:57:22

您可以将两个数字组合成一个字符串,并使用 SHA1 基于该字符串生成哈希值。

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

挖鼻大婶 2024-10-10 00:57:22

如果 X & Y 是 Int 添加分隔符。总是独一无二的。

X=100,Y=5=> 100.5X

=1023232,Y=44=> 1023232.44

If X & Y are Int add a seperator. Always unique.

X = 100, Y = 5 => 100.5

X = 1023232, Y = 44 => 1023232.44

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文