Golang Optimization Road--cantor Pair

Source: Internet
Author: User
Tags sprintf
This is a creation in Article, where the information may have evolved or changed.

Write in front

A certain object is uniquely determined by two IDs, how do you handle this data structure to quickly find and conserve memory? Let's start with a stupid method--a string to deal with. It's easier to think about (I think the simplest and most simple and rough way to do this is to use string to engage in it).

fmt.Sprintf("%d_%d", id1, id2)

That's it. stored in a string to save, when the query comparison with the method of the string to calculate. Of course, storing and computing numbers as strings is an extremely wasteful memory and CPU.

Cantor Pairing Function Introduction

Cantor pairing-Cantor pairing function is a method of turning two natural numbers into a unique natural number. The concrete principle I will not say, I also can not understand ... To put it simply:

    • Only natural numbers are supported. Natural numbers are integers (natural numbers include positive integers and 0);
    • Support inverse solution;
    • f(k1, k2)And the f(k2, k1) results obtained are different. Of course, if you want to get the same is also possible, the calculation of support to the two number of sequential order;
    • The results are likely to be much k1 larger and more important k2 to be aware of the overflow problem.

Example

This algorithm has only one formula, which is easy to implement. I simply made a wheel of my own, pairing. For the derivation of the formula, please visit Wikipedia.

import "github.com/mnhkahn/pairing"pair := pairing.Encode(k1, k2)k3, k4 := pairing.Decode(pair2)

Supports forward encoding and reverse decoding.

Realize

import "math"func Encode(k1, k2 uint64) uint64 {pair := k1 + k2pair = pair * (pair + 1)pair = pair / 2pair = pair + k2return pair}
    • Func Decode (pair UInt64) (UInt64, UInt64) {w: = Math. Floor (Math. Sqrt (float64 (8pair+1))-1)/2) T: = (ww + W)/2

        k2 := pair - uint64(t)  k1 := uint64(w) - k2  return k1, k2   }

Comparison with other data structures

One of the things to compare is the comparison with the string mentioned earlier. There is also a workaround: Two integers int32 , this 64-digit number stitching a int64 inside, the first number accounted for the top 32, the latter a number accounted for 32, is also a feasible scheme. We can call this method a bit method.

func EncodeBit(k1, k2 uint32) uint64 {pair := uint64(k1)<<32 | uint64(k2)return pair}func DecodeBit(pair uint64) (uint32, uint32) {k1 := uint32(pair >> 32)k2 := uint32(pair) & 0xFFFFFFFFreturn k1, k2}

Easier to implement. How does the performance compare with Cantor pair?

Import ("FMT" "testing") var test_pairs = [][]uint64{[]uint64{0, 0},[]uint64{0, 1},[]uint64{1, 0},}var test_ress = [] Uint64{0,2,1,}var test_resbits = []uint64{0,1,4294967296,}func testpair (t *testing. T) {For i, p: = Range Test_pairs {A, B: = P[0], p[1]if pair: = Encode (A, b); Pair! = Test_ress[i] {t.error (A, B, pair)}}FO  R I, p: = Range Test_pairs {A, B: = P[0], P[1]pair: = Test_ress[i]if x, y: = Decode (pair); X! = a | | Y! = b {T.error (A, B, Pair)}}fmt. Println (Encode (559, 83792)) for I, p: = Range Test_pairs {A, B: = UInt32 (P[0]), UInt32 (p[1]) if pair: = Encodebit (A, b); Pai r! = Test_resbits[i] {t.error (A, B, pair)}}for I, p: = Range Test_pairs {A, B: = UInt32 (P[0]), UInt32 (p[1]) Pair: = Test_re Sbits[i]if x, Y: = Decodebit (pair); X! = A | | Y! = b {T.error (A, B, pair)}}fmt. Println (Encodebit (559, 83792))}func Benchmarkencode (b *testing. b) {for i: = 0; i < B.N; i++ {Encode (559, 83792)}}func Benchmarkdecode (b *testing. B) {for i: = 0; i < B.N; i++ {Decode (3557671568)}}func BenchmarkencodebiT (b *testing. b) {for i: = 0; i < B.N; i++ {encodebit (559, 83792)}}func benchmarkdecodebit (b *testing. b) {for i: = 0; i < B.N; i++ {decodebit (2400886802256)}}func benchmarkencodestr (b *testing. B) {for i: = 0; i < B.N; i++ {_ = Fmt. Sprintf ("%d_%d", 559, 83792)}}/*go test-bench=. -benchmembenchmarkencode-2 2000000000 0.37 ns/op 0 b/op 0 Allocs/opbenchmarkdecode               -2 50000000 26.9 ns/op 0 b/op 0 allocs/opbenchmarkencodebit-2 2000000000            0.37 ns/op 0 b/op 0 allocs/opbenchmarkdecodebit-2 2000000000 0.37 ns/op          0 b/op 0 allocs/opbenchmarkencodestr-2 5000000 271 ns/op 3 allocs/op*/

Conclusion

    • The worst performance is saved with a string, and the remaining two is 400 times times the performance;
    • The performance of Cantor pair and bit method is quite, and the performance of inverse solution is also checked;
    • Since the performance is quite, although this article focuses on the Cantor pair algorithm, but I still suggest that if the bit method can meet your needs, especially when the number range is small, it is better to use this. A simple approach will make you more comfortable with maintenance, even if you understand how the complex formulas are derived ^ ^.

Please refer to the complete source code in this article.

Original link: Golang optimization road--cantor Pair, reproduced please indicate the source!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.