Mapping two integers to one, in a unique and deterministic way

前端 未结 19 2106
不知归路
不知归路 2020-11-22 09:35

Imagine two positive integers A and B. I want to combine these two into a single integer C.

There can be no other integers D and E which combine to C. So combining

相关标签:
19条回答
  • 2020-11-22 10:01

    Given positive integers A and B, let D = number of digits A has, and E=number of digits B has The result can be a concatenation of D, 0, E, 0, A, and B.

    Example: A = 300, B = 12. D = 3, E=2 result = 302030012. This takes advantage of the fact that the only number that starts with 0, is 0,

    Pro: Easy to encode, easy to decode, human readable, significant digits can be compared first, potential for compare without calculation, simple error checking.

    Cons: Size of results is an issue. But that's ok, why are we storing unbounded integers in a computer anyways.

    0 讨论(0)
  • 2020-11-22 10:02

    Let number a be the first, b the second. Let p be the a+1-th prime number, q be the b+1-th prime number

    Then, the result is pq, if a<b, or 2pq if a>b. If a=b, let it be p^2.

    0 讨论(0)
  • 2020-11-22 10:04

    You're looking for a bijective NxN -> N mapping. These are used for e.g. dovetailing. Have a look at this PDF for an introduction to so-called pairing functions. Wikipedia introduces a specific pairing function, namely the Cantor pairing function:

    pi(k1, k2) = 1/2(k1 + k2)(k1 + k2 + 1) + k2

    Three remarks:

    • 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
    0 讨论(0)
  • 2020-11-22 10:04

    f(a, b) = s(a+b) + a, where s(n) = n*(n+1)/2

    • This is a function -- it is deterministic.
    • It is also injective -- f maps different values for different (a,b) pairs. You can prove this using the fact: s(a+b+1)-s(a+b) = a+b+1 < a.
    • It returns quite small values -- good if your are going to use it for array indexing, as the array does not have to be big.
    • It is cache-friendly -- if two (a, b) pairs are close to each other, then f maps numbers to them which are close to each other (compared to other methods).

    I did not understand what You mean by:

    should always yield an integer on either the positive or the negative side of integers

    How can I write (greater than), (less than) characters in this forum?

    0 讨论(0)
  • 2020-11-22 10:08

    For positive integers as arguments and where argument order doesn't matter:

    1. Here's an unordered pairing function:

      <x, y> = x * y + trunc((|x - y| - 1)^2 / 4) = <y, x>
      
    2. For x ≠ y, here's a unique unordered pairing function:

      <x, y> = if x < y:
                 x * (y - 1) + trunc((y - x - 2)^2 / 4)
               if x > y:
                 (x - 1) * y + trunc((x - y - 2)^2 / 4)
             = <y, x>
      
    0 讨论(0)
  • 2020-11-22 10:08

    What you suggest is impossible. You will always have collisions.

    In order to map two objects to another single set, the mapped set must have a minimum size of the number of combinations expected:

    Assuming a 32-bit integer, you have 2147483647 positive integers. Choosing two of these where order doesn't matter and with repetition yields 2305843008139952128 combinations. This does not fit nicely in the set of 32-bit integers.

    You can, however fit this mapping in 61 bits. Using a 64-bit integer is probably easiest. Set the high word to the smaller integer and the low word to the larger one.

    0 讨论(0)
提交回复
热议问题