62

is there some way to create unique number from 2 positive integer numbers? Result must be unique even for these pairs: 2 and 30, 1 and 15, 4 and 60. In general, if I take 2 random numbers result must be unique(or with very high probability unique)

Thanks a lot

EDIT: calculation is for computer program,so computational complexity is important

drizzt
  • 689
  • You do not specify what you mean by making a number out of two numbers. – shuhalo Feb 24 '11 at 09:17
  • 3
    Are the pairs ordered? Should 2 and 30 produce the same answer as 30 and 2? – Henry Feb 24 '11 at 10:02
  • 2and30,30and2 are two different pairs – drizzt Feb 24 '11 at 10:52
  • 6
    I don't get the bounty. Alex Kruckman gave a very good answer whose computational complexity is essentially $O(1)$ if I am not mistaken. Can you please specify what is wrong with the answer given so far? – Asaf Karagila Mar 08 '11 at 22:20
  • I agree with Asaf. Alex Kruckman's answer mentions a quite fast pairing function. If you are really concerned about the efficiency of the algorithm (for reading and writing), then you should probably look for some other ways of combining two numbers, like a list or an ordered pair, or whatever your language supports. But as far as standard mathematical pairing functions go, Cantor's is reasonably quick. Of course, it would be much easier to answer your question appropriately if we knew what your motivation is. – Abel Mar 09 '11 at 01:41
  • Is there any way to force people to give the bounty. It looks like this problem has been solved a long time ago?? – Fabian Mar 09 '11 at 16:29
  • there is no way to force to give the bounty, but bounty can be given only after some time – drizzt Mar 12 '11 at 10:15
  • Depending on the particular context and problem at hand, a "non-mathematical hack" might be to simply convert the two integers to strings, concatenate them and cast the result back to an integer if necessary. For this to produce the desired result, you might need to partition and sort the dataset correctly beforehand, e.g. if you are going to use the result for ranking purposes. Computationally, this would likely be a relatively cheap operation. – leifericf Jul 27 '20 at 09:02
  • @leifericf: the top answer here is much cheaper for integers, especially if you meant base 10. Each base10 digit requires dividing by 10 and getting the remainder. A multiplicative inverse can make that not too slow, but it's still one decimal digit at a time, vs. 3 adds, a multiply, and a right shift for the Cantor pairing function. So the whole thing is about as cheap as getting one decimal digit from one of the inputs. Or turning one input into hex if you use clever SIMD operations for it, especially AVX-512. – Peter Cordes Nov 10 '22 at 23:31
  • If numbers have an upper bound $U$, a relatively simple function is:
    $$f(a, b) = aU + b$$ To recover $a$ and $b$ from $N := f(a, b)$, the following can be used: $$a = \operatorname{truncate}(N / u), \qquad b = N \operatorname{%} u,$$ where $%$ is the modulo operator.
    – Javier TG Mar 22 '23 at 11:00

6 Answers6

97

The sort of function you are looking for is often called a pairing function.

A standard example is the Cantor pairing function $\mathbb{N}\times\mathbb{N}\rightarrow\mathbb{N}$, given by: $\pi(a,b) = \frac{1}{2}(a+b)(a+b+1) + b$.

You can find more information here: http://en.wikipedia.org/wiki/pairing_function

Alex Kruckman
  • 76,357
  • thanks, this is good advice. can you suggest me which pairing function has the smallest computational complexity? – drizzt Mar 08 '11 at 21:24
  • If you're looking for something of minimal computational complexity for a computer to handle, you could use an "infinite hotel" type construction where you think of the number as its binary expansion -- a list of 0's and 1's and then you "merge" the list by taking one term from each number, in succession. – Ryan Budney Mar 08 '11 at 22:21
  • 1
    That's not necessarily the cheapest way, it depends on what you're counting. In most actual computers, there is a multiplication at a reasonable price, while zipping two binary expansions will take many operations. The Cantor pairing function is the cheapest in actual applications, with only three(!) additions, one multiplication, and a single right shift (to get the $\tfrac12$). – Rhymoid Dec 24 '12 at 18:19
  • 7
    Just to make it clear, this formula DOES NOT GENERATE the same output when you change the order of A and B, e.g: f(A,B) != f(B,A). – Placeholder Oct 21 '14 at 12:53
  • @GANGSTAIRL seems like a plus to me :)! – Thomas Wagenaar Apr 17 '17 at 12:26
  • I actually have a similar question, but I'm not familiar with the math here and I don't think I should open a new question, so... does a pairing function for $\mathbb{N}\times\mathbb{N}\times\mathbb{N}\rightarrow\mathbb{N}$ look like this: $\Pi(a, b, c) = \frac{1}{2}(a + b + c)(a + b + c + 1)+b$? – Alexis Purslane Jan 07 '19 at 03:27
  • @ChristopherDumas No - one reason your suggestion doesn't work is that $\Pi(a,b,c) = \Pi(c,b,a)$. There are many "tripling" functions $\mathbb{N}\times\mathbb{N}\times \mathbb{N}\to \mathbb{N}$. One way to generalize any pairing function $\pi$ to a tripling function $\Pi$ is to define $\Pi(a,b,c) = \pi(\pi(a,b),c)$. When $\pi$ is the Cantor pairing function from my answer: $$\Pi(a,b,c) = \frac{1}{2}\left(\frac{1}{2}(a+b)(a+b+1)+b+c\right)\left(\frac{1}{2}(a+b)(a+b+1)+b + c + 1\right) + c.$$ – Alex Kruckman Feb 04 '19 at 15:07
  • Will this also work if one of the numbers is Zero? – hobwell Nov 06 '19 at 20:06
  • 3
    @hobwell Yes ($0\in \mathbb{N}$). If you visit the wikipedia page I linked to in my answer, you'll find a graphical representation of what this function does, and you can see clearly from that picture that it includes ordered pairs of natural numbers of the form $(0,b)$ and $(a,0)$ in the domain of the function. – Alex Kruckman Nov 06 '19 at 22:07
  • @drizzt: This one looks very cheap to compute for integers. Note that a+b is a common sub-expression, so one addition of a+b, one copy-and-increment of that (e.g. x86 LEA), one multiply and right shift, one more addition of b. (For signed integers, /2 in most languages will compile to multiple operations to truncate toward 0, unlike arithmetic right shift which rounds towards -inf. So use a right shift, or cast the product to unsigned before dividing. sum * (sum+1) can't be negative unless there's integer overflow and it wraps, since both terms have the same sign except -1 * 0) – Peter Cordes Nov 10 '22 at 23:10
  • Interleaving the binary representations can be fast if you have a modern x86 with fast pdep (to spread out each number with 0s, allowing one lea rax, [rsi + rdi*2] to combine them). Intel since Haswell, AMD since Zen3 have fast pdep. Or carryless multiply if you already have your integers in appropriate registers for that (XMM vectors on x86). Squaring a number with clmul interleaves its bits with zeros. See The interstice of two binary numbers on code-golf for commented x86 asm examples. (That question wants them interleaved both ways) – Peter Cordes Nov 10 '22 at 23:19
  • If you have fixed-width integers, and you can produce a result with twice the width, it's very cheap to do ((uint64_t)x<<32) + y to concatenate the bits of two uint32_t inputs. But that makes huge values even when both inputs are small, which is probably undesirable. – Peter Cordes Nov 10 '22 at 23:21
29

if the numbers are $a$ and $b$, take $2^a3^b$. This method works for any number of numbers (just take different primes as the bases), and all the numbers are distinct.

  • 8
    This method generates exceptionally large numbers fairly quickly. (2^1023 on it's own is 8.9885E+307). If you're using this in excel 2^1023.9 is your upper limit) – Bradley Sep 02 '16 at 23:05
5

Google pairing function. As I mentioned in the similar question, there are also other pairing functions besides the well-known one due to Cantor. For example, see this "elegant" pairing function, which has the useful property that it orders many expressions by depth.

Bill Dubuque
  • 272,048
4

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

  1. Here's an unordered pairing function:

    $<x, y> = x * y + trunc(\frac{(|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>
    
ma11hew28
  • 141
3

You could try the function by Matthew Szudzik, which is given as: $$a \geq b ~?~ a*a + a + b : a+b*b$$

In other words: $$(a,b)\mapsto \begin{cases} a^2 + a + b & \text{if } a \geq b\\ a + b^2 & \text{if } a < b \end{cases}$$

I found it here, which is a similar question as this.

Alex Kruckman
  • 76,357
jayesh
  • 41
1

Apologies for resurrecting this ancient question, but I've noticed that there are collisions in the results of the Cantor pairing function.

For example, I've noticed that when a and b are 0.0 and 0.0, or 0.6 and 0.0 the result is the same: 0.48.

Is this function expected to work for non-discrete numbers, or does this have something to do with the fact they the numbers are 0.0 and 0.0 in the former case?