想象两个正整数A和b,我想把这两个组合成一个整数C。
不可能有其他整数D和E组合成C。 所以把它们和加法运算符结合是不行的。例:30 + 10 = 40 = 40 + 0 = 39 + 1 连接也不管用。例如“31”+“2”= 312 =“3”+“12”
这种组合操作也应该是确定的(总是用相同的输入产生相同的结果),并且应该总是在整数的正侧或负侧产生一个整数。
想象两个正整数A和b,我想把这两个组合成一个整数C。
不可能有其他整数D和E组合成C。 所以把它们和加法运算符结合是不行的。例:30 + 10 = 40 = 40 + 0 = 39 + 1 连接也不管用。例如“31”+“2”= 312 =“3”+“12”
这种组合操作也应该是确定的(总是用相同的输入产生相同的结果),并且应该总是在整数的正侧或负侧产生一个整数。
当前回答
你正在寻找一个双射NxN - >n映射。这些是用于例如燕尾。请看这个PDF文件,它介绍了所谓的配对函数。维基百科介绍了一个特定的配对函数,即康托配对函数:
备注:三个
As others have made clear, if you plan to implement a pairing function, you may soon find you need arbitrarily large integers (bignums). If you don't want to make a distinction between the pairs (a, b) and (b, a), then sort a and b before applying the pairing function. Actually I lied. You are looking for a bijective ZxZ -> N mapping. Cantor's function only works on non-negative numbers. This is not a problem however, because it's easy to define a bijection f : Z -> N, like so: f(n) = n * 2 if n >= 0 f(n) = -n * 2 - 1 if n < 0
其他回答
假设你有一个32位整数,为什么不把a移到前16位的一半,把B移到另一半?
def vec_pack(vec):
return vec[0] + vec[1] * 65536;
def vec_unpack(number):
return [number % 65536, number // 65536];
除了尽可能节省空间和计算成本之外,一个非常酷的副作用是,您可以在填充的数字上进行向量计算。
a = vec_pack([2,4])
b = vec_pack([1,2])
print(vec_unpack(a+b)) # [3, 6] Vector addition
print(vec_unpack(a-b)) # [1, 2] Vector subtraction
print(vec_unpack(a*2)) # [4, 8] Scalar multiplication
对于作为参数的正整数和参数顺序无关的情况:
下面是一个无序配对函数: < x, y > = x * y + trunc ((x - y | | - 1) ^ 2 / 4) = < y、x > 对于x≠y,这里有一个唯一的无序配对函数: <x, y> = if x < y: X * (y - 1) + trunc((y - X - 2)²/ 4) 如果x > y: (x - 1) * y + trunc((x - y - 2)^2 / 4) = <y, x>
如果你想要更多的控制,比如为第一个数字分配X位,为第二个数字分配Y位,你可以使用下面的代码:
class NumsCombiner
{
int num_a_bits_size;
int num_b_bits_size;
int BitsExtract(int number, int k, int p)
{
return (((1 << k) - 1) & (number >> (p - 1)));
}
public:
NumsCombiner(int num_a_bits_size, int num_b_bits_size)
{
this->num_a_bits_size = num_a_bits_size;
this->num_b_bits_size = num_b_bits_size;
}
int StoreAB(int num_a, int num_b)
{
return (num_b << num_a_bits_size) | num_a;
}
int GetNumA(int bnum)
{
return BitsExtract(bnum, num_a_bits_size, 1);
}
int GetNumB(int bnum)
{
return BitsExtract(bnum, num_b_bits_size, num_a_bits_size + 1);
}
};
我总共使用了32位。这里的想法是,如果你想让第一个数字最多10位,第二个数字最多12位,你可以这样做:
NumsCombiner nums_mapper(10/*bits for first number*/, 12/*bits for second number*/);
现在可以在num_a中存储2^10 - 1 = 1023的最大值,在num_b中存储2^12 - 1 = 4095的最大值。
设置num A和num B的值。
int bnum = nums_mapper.StoreAB(10/*value for a*/, 12 /*value from b*/);
现在bnum是所有的位(总共32位)。您可以将代码修改为使用64位) 要得到num a:
int a = nums_mapper.GetNumA(bnum);
要得到num b:
int b = nums_mapper.GetNumB(bnum);
编辑: Bnum可以存储在类中。我做这件事不是因为我自己的需要 我分享了代码,希望对您有所帮助。
感谢来源: https://www.geeksforgeeks.org/extract-k-bits-given-position-number/ 对于函数提取位,也感谢mouviciel在这篇文章中的回答。 利用这些资源,我可以找出更先进的解决方案
f(a, b) = s(a+b) + a,其中 s(n) = n*(n+1)/2
这是一个函数,它是确定的。 它也是单射的——f映射不同(a,b)对的不同值。你可以证明 它使用的事实是:s(a+b+1)-s(a+b) = a+b+1 <一个。 它返回非常小的值——如果你打算用它来做数组索引,那很好,因为数组不需要很大。 它是缓存友好的——如果两个(a, b)对彼此接近,那么f将彼此接近的数字映射到它们(与其他方法相比)。
我不明白您所说的:
应该总是产生一个整数 不管是积极的还是消极的 整数的边
我如何在这个论坛写(大于),(小于)字符?
你正在寻找一个双射NxN - >n映射。这些是用于例如燕尾。请看这个PDF文件,它介绍了所谓的配对函数。维基百科介绍了一个特定的配对函数,即康托配对函数:
备注:三个
As others have made clear, if you plan to implement a pairing function, you may soon find you need arbitrarily large integers (bignums). If you don't want to make a distinction between the pairs (a, b) and (b, a), then sort a and b before applying the pairing function. Actually I lied. You are looking for a bijective ZxZ -> N mapping. Cantor's function only works on non-negative numbers. This is not a problem however, because it's easy to define a bijection f : Z -> N, like so: f(n) = n * 2 if n >= 0 f(n) = -n * 2 - 1 if n < 0