독특하고 결정적인 방식으로 두 정수를 하나로 매핑


235

두 개의 양의 정수 A와 B를 상상해보십시오.이 두 개를 단일 정수 C로 결합하고 싶습니다.

C와 결합하는 다른 정수 D와 E는있을 수 없습니다. 따라서 더하기 연산자와 결합하면 작동하지 않습니다. 예 : 30 + 10 = 40 = 40 + 0 = 39 + 1 연결도 작동하지 않습니다. 예 : "31"+ "2"= 312 = "3"+ "12"

이 결합 조작은 결정되어야한다 (항상 같은 입력과 같은 결과를 수득) 항상 양 또는 음의 정수의 어느 측에 정수를 산출한다.


10
소프트웨어의 정수 또는 수학의 정수를 의미하는지 명확히해야합니다. 소프트웨어에서 정수 유형을 선택하면 크기가 정해 지므로 유한 한 수를 가지므로 해결책이 없습니다 (물론 입력 데이터가 특정 범위 내에 있고 출력이 모든 정수). 수학에서 ASk의 솔루션을 참조하십시오.
Daniel Daranas

낮은 양수 범위의 경계 정수에 대해 이야기하고 있습니다. 0에서 10,000으로 말
피해

27
@ harm : 그럼 어떻 10,001*A + B습니까?
BlueRaja-대니 Pflughoeft

2
이 PHP 함수를 찾았습니다 : gist.github.com/hannesl/8031402
cakan

예를 들어 (3,12) & (12,3)과 같은 순서가 중요하지 않은 경우 "A + B"+ "A * B"를 사용합니다
Sodj

답변:


233

당신은 bijective NxN -> N매핑을 찾고 있습니다. 이것들은 예를 들어 더브 테일링에 사용됩니다 . 페어링 기능 에 대한 소개 는 이 PDF 를 참조하십시오 . Wikipedia는 특정 페어링 기능, 즉 Cantor 페어링 기능을 소개합니다 .

파이 (k1, k2) = 1/2 (k1 + k2) (k1 + k2 + 1) + k2

세 가지 언급 :

  • 다른 사람들이 분명히 알 수 있듯이 페어링 기능을 구현하려는 경우 곧 큰 정수 (bignums)가 필요할 수 있습니다.
  • 쌍 (a, b)와 (b, a)를 구별하지 않으려면 페어링 기능을 적용하기 전에 a와 b를 정렬하십시오.
  • 사실 나는 거짓말을했다. 당신은 bijective ZxZ -> N매핑을 찾고 있습니다. Cantor의 기능은 음수가 아닌 숫자에서만 작동합니다. 그러나 다음 f : Z -> N과 같이 bijection을 쉽게 정의 할 수 있으므로 문제가되지 않습니다 .
    • n> = 0 인 경우 f (n) = n * 2
    • n <0 인 경우 f (n) = -n * 2-1

13
+1 나는 이것이 무제한 정수에 대한 정답이라고 생각합니다.
알 수 없음

4
k1, k2의 값을 어떻게 다시 얻을 수 있습니까?
MinuMaster

3
@MinuMaster : 동일한 Wikipedia 기사 의 Cantor 페어링 기능 반전 아래에 설명되어 있습니다 .
Stephan202

4
아래의 newfal에 의해 설명 된 Szudzik의 기능을 참조하십시오.
OliJG

1
이것은 제한되지 않은 정수에 대해서는 맞지만, 제한되는 정수에는 적합하지 않습니다. @ blue-raja의 의견이 훨씬 합리적이라고 생각합니다.
Kardasis

226

캔터 페어링 기능은 정말 빨리 간단한을 고려 거기 더 나은 사람 중 하나, 공간 효율적이지만 더 나은 볼프람에 게시 무언가가 여기에, 매튜 Szudzik으로는 . Cantor pairing 기능의 한계는 (상대적으로) 2N입력이 2 N비트 정수인 경우 인코딩 된 결과의 범위가 항상 비트 정수 의 한계 내에 머 무르지 않는다는 것 입니다. 내 입력이 두 경우 즉, 16에 이르기까지 비트 정수는 0 to 2^16 -1다음이 있습니다 2^16 * (2^16 -1)가능한 입력의 조합이 이렇게 명백한에 의해, 미루다 원리 , 우리는 적어도 크기의 출력이 필요 2^16 * (2^16 -1)동일, 2^32 - 2^16또는 다른 말로,의지도를32비트 번호는 이상적으로 실현 가능해야합니다. 이것은 프로그래밍 세계에서 실질적으로 중요하지 않을 수 있습니다.

캔터 페어링 기능 :

(a + b) * (a + b + 1) / 2 + a; where a, b >= 0

최대 16 비트 정수 두 개 (65535, 65535)에 대한 매핑은 8589803520이며 32 비트에는 맞지 않습니다.

Szudzik의 기능을 입력하십시오 :

a >= b ? a * a + a + b : a + b * b;  where a, b >= 0

(65535, 65535)에 대한 매핑은 이제 4294967295이며 32 비트 (0 ~ 2 ^ 32 -1) 정수입니다. 이것이이 솔루션이 이상적인 곳이며, 해당 공간의 모든 단일 지점을 활용하기 때문에 더 효율적인 공간을 확보 할 수있는 것은 없습니다.


이제 우리가 일반적으로 언어 / 프레임 워크에서 다양한 크기의 부호있는 구현을 처리한다는 사실을 고려하여 signed 16비트 정수 범위에서 범위를 고려해 봅시다 -(2^15) to 2^15 -1(나중에 부호 범위까지 확장하기 위해 출력을 확장하는 방법을 살펴 보겠습니다). 이후 a및 것은 b그들이 범위 긍정적해야 0 to 2^15 - 1.

캔터 페어링 기능 :

최대 16 비트 부호있는 정수 2 개 (32767, 32767)에 대한 매핑은 부호있는 32 비트 정수의 최대 값보다 짧은 2147418112입니다.

이제 Szudzik의 기능 :

(32767, 32767) => 1073741823, 훨씬 작습니다.

음의 정수를 고려해 봅시다. 그것은 내가 아는 원래의 질문을 넘어서지 만 미래 방문자를 돕기 위해 정교하게 만듭니다.

캔터 페어링 기능 :

A = a >= 0 ? 2 * a : -2 * a - 1;
B = b >= 0 ? 2 * b : -2 * b - 1;
(A + B) * (A + B + 1) / 2 + A;

(-32768, -32768) => 8589803520이며 Int64입니다. 16 비트 입력을위한 64 비트 출력은 용납 할 수 없습니다 !!

Szudzik의 기능 :

A = a >= 0 ? 2 * a : -2 * a - 1;
B = b >= 0 ? 2 * b : -2 * b - 1;
A >= B ? A * A + A + B : A + B * B;

(-32768, -32768) => 4294967295 : 부호없는 범위의 경우 32 비트 또는 부호있는 범위의 경우 64 비트이지만 여전히 더 좋습니다.

출력이 항상 양의 동안이 모든 것. 부호있는 세계에서는 출력의 절반을 음의 축으로 전송할 수 있으면 공간이 훨씬 절약됩니다 . Szudzik의 경우 다음과 같이 할 수 있습니다.

A = a >= 0 ? 2 * a : -2 * a - 1;
B = b >= 0 ? 2 * b : -2 * b - 1;
C = (A >= B ? A * A + A + B : A + B * B) / 2;
a < 0 && b < 0 || a >= 0 && b >= 0 ? C : -C - 1;

(-32768, 32767) => -2147483648

(32767, -32768) => -2147450880

(0, 0) => 0 

(32767, 32767) => 2147418112

(-32768, -32768) => 2147483647

내가하는 일 : 2입력에 가중치를 적용 하고 함수를 거친 후 출력을 2로 나누고을 곱하여 출력을 음의 축으로 가져갑니다 -1.

부호있는 16비트 수 범위의 입력에 대한 결과 는 출력이 부호있는 32비트 정수 의 한계 내에 있습니다 . Cantor 페어링 기능에 대해 동일한 방법을 사용하는 방법을 잘 모르겠지만 효율적이지 않은 방법으로 시도하지 않았습니다. 또한 Cantor 페어링 기능과 관련된 계산이 많을수록 속도가 느려집니다 .

다음은 C # 구현입니다.

public static long PerfectlyHashThem(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;
}

public static int PerfectlyHashThem(short a, short b)
{
    var A = (uint)(a >= 0 ? 2 * a : -2 * a - 1);
    var B = (uint)(b >= 0 ? 2 * b : -2 * b - 1);
    var C = (int)((A >= B ? A * A + A + B : A + B * B) / 2);
    return a < 0 && b < 0 || a >= 0 && b >= 0 ? C : -C - 1;
}

중간 계산이 2N부호있는 정수의 한계를 초과 할 수 있기 때문에 4N정수 유형 을 사용했습니다 (마지막 나누기 2는 결과를 로 가져옵니다 2N).

대체 솔루션에서 제공 한 링크는 공간의 모든 단일 지점을 활용하는 함수의 그래프를 멋지게 묘사합니다. 한 쌍의 좌표를 가역적으로 단일 숫자로 고유하게 인코딩 할 수 있다는 것이 놀랍습니다! 숫자의 마법 세계 !!


5
부호있는 정수에 대해 수정 된 언해시 함수는 무엇입니까?
Arets Paeglis

7
이 대답은 나를 혼란스럽게합니다. 단일 숫자를 (0,0)통해 매핑 (65535,65535)하려면 a<<16 + b기본적으로 모든면 에서 더 빠릅니다 (더 빠르고 간단하고 이해하기 쉽고 명확합니다) . 네가 원한다면(-32768,-32768)(327687,327687)대신에, 단지 대상이 32768이 처음.
BlueRaja-대니 Pflughoeft

2
@ BlueRaja-DannyPflughoeft 당신이 맞아요. 범위가 제한되지 않거나 알 수없는 경우 내 대답은 유효합니다. 업데이트하겠습니다. 나는 나에게 한계가 중요하기 전에 그것을 작성했다. 이 답변을 편집하는 것은 오랫동안 내 마음에 있습니다. 나는 곧 시간을 찾을 것입니다.
nawfal

Szudzik의 함수는 조합 또는 순열에 작동합니까? 순열 인 것 같습니다. 조합에 사용하려는 경우 알고리즘의 IF 및 기타 부분을 제거 할 수 있습니까?
Jamie Marshall

다음은 길이에 상관없이 튜플에 일반화 된 Szudzik 함수의 Python 구현입니다. gitlab.com/snippets/32559
Doctor J

47

A와 B를 2 바이트로 표현할 수 있으면 4 바이트로 결합 할 수 있습니다. A를 최상위 반에, B를 최하 반에 놓습니다.

C 언어에서 이것은 (sizeof (short) = 2 및 sizeof (int) = 4라고 가정)를 제공합니다.

int combine(short A, short B)
{
    return A<<16 | B;
}

short getA(int C)
{
    return C>>16;
}

short getB(int C)
{
    return C & 0xFFFF;
}

3
combine()return (unsigned short)(A<<16) | (unsigned short)(B); 음수를 올바르게 포장 할 수 있도록 해야합니다 .
Andy

2
@ 앤디 A<<16는 한계를 벗어날 것입니다. 그것은해야한다return (unsigned int)(A<<16) | (unsigned short)(B);
DanSkeel

15

이것도 가능합니까?
두 정수를 결합하고 있습니다. 둘 다 -2,147,483,648에서 2,147,483,647의 범위를 가지지 만 긍정적 인 것만 취할 것입니다. 2147483647 ^ 2 = 4,61169E + 18 조합이됩니다. 각 조합은 고유해야하며 정수가되므로이 양의 숫자를 포함 할 수있는 일종의 마법 정수가 필요합니다.

아니면 내 논리에 결함이 있습니까?


+1 저도 그렇게 생각합니다 (A와 B의 순서는 중요하지 않다고 계산을했지만)
lc.

4
네, 당신의 논리는 비둘기 구멍 원리에 의해 정확합니다. 불행히도 asker는 정수가 바인드되었는지 여부를 지정하지 않았습니다.
알 수 없음

그렇습니다. 나도 그렇게 생각했지만 메시지가 본질적으로 동일하다고 생각했기 때문에 리 캘링을 귀찮게하지 않았습니다.
Boris Callens

또한 방금 확률 계산 (네덜란드어의 문자 번역) 교과서를 다시 가져와야한다는 것을 깨달았습니다.
Boris Callens

2
@Boris : Kansrekening은 "확률 이론"입니다.
Stephan202

8

양의 정수에 대한 표준 수학적 방법은 소인수 분해의 고유성을 사용하는 것입니다.

f( x, y ) -> 2^x * 3^y

단점은 이미지가 상당히 넓은 정수 범위에 걸쳐 있기 때문에 컴퓨터 알고리즘에서 매핑을 표현할 때 결과에 ​​적합한 유형을 선택하는 데 문제가있을 수 있다는 것입니다.

당신은 부정적인를 처리하려면이 옵션을 수정할 수 xy 5 개, 7 용어의 힘으로 플래그를 인코딩하여.

예 :

f( x, y ) -> 2^|x| * 3^|y| * 5^(x<0) * 7^(y<0)

수학은 괜찮습니다. 그러나 Boris가 말했듯이 이것을 컴퓨터 프로그램으로 실행하려면 기계의 유한도를 고려해야합니다. 알고리즘은 관련 기계에서 표현할 수있는 정수의 서브 세트에 대해 올바르게 작동합니다.
Yuval F

2
나는 두 번째 단락에서 이것을 진술했다. 질문의 태그는 특정 언어가 아닌 '알고리즘', '수학적'및 '결정적'을 나타냅니다. 입력 범위가 제한되지 않고 환경에 무제한 정수 유형 'bigint'가있을 수 있습니다.
CB Bailey

8

숫자를 a첫 번째, b두 번째로 둡니다. 하자 pa+1번째 소수를 qb+1번째 소수

그런 다음 결과는 pqif a<b,또는 2pqif a>b입니다. 경우 a=b, 그것은하자 p^2.


4
NP 솔루션을 원할 것입니다.
user44242

1
이것이 a = 5, b = 14 및 a = 6, b = 15에 대해 동일한 결과를 생성하지 않습니까?
Lieven Keersmaekers

3
서로 다른 두 소수의 두 곱은 동일한 결과를 가질 수 없습니다 (고유 소수 분해) a = 5, b = 14-> 결과는 13 * 47 = 611 a = 6, b = 15-> 결과는 17 * 53 = 901
ASk

4

매핑을 구성하는 것은 그리 어렵지 않습니다.

   1 2 3 4 5 (a, b)! = (b, a) 인 경우이 매핑을 사용하십시오.
1,012 6 10
2 4 7 11 16
3 5 8 12 17 23
4 9 13 18 24 31
5 14 19 25 32 40

   1 2 3 4 5 (a, b) == (b, a) (거울) 인 경우이 매핑을 사용하십시오.
10012 4 6
2 1 3 5 7 10
3 2 5 8 11 14
44 8 11 15 19
5 6 10 14 19 24


    0 1 -1 2 -2 음수 / 양수가 필요한 경우 사용하십시오
 0012 6
 11 3 5 7 10
-12 5 8 11 14
 2 4 8 11 15 19
-2 6 10 14 19 24

임의의 a, b에 대한 값을 얻는 방법을 알아내는 것은 조금 더 어렵습니다.


4

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..
  • 배열이 클 필요는 없으므로 배열 인덱싱에 사용하려는 경우 아주 작은 값을 반환합니다.
  • 캐시에 친숙합니다. 두 (a, b) 쌍이 서로 가까이 있으면 f는 숫자를 서로 가까운 (다른 방법과 비교하여) 숫자로 매핑합니다.

나는 당신이 의미하는 바를 이해하지 못했습니다 :

정수의 양 또는 음의 정수를 항상 산출해야합니다.

이 포럼에서 (보다 큼) 문자를 쓰려면 어떻게해야합니까?


2
보다 크거나 작은 문자는에서 제대로 작동해야합니다 backtick escapes.
TRiG

이것은 Cantor 페어링 기능과 동일하며 음의 정수에서는 작동하지 않습니다.
Davor Josipovic

4

Stephan202의 답변이 유일한 일반적인 답변이지만 범위가 제한된 정수의 경우 더 잘 수행 할 수 있습니다. 예를 들어 범위가 0..10,000이면 다음을 수행 할 수 있습니다.

#define RANGE_MIN 0
#define RANGE_MAX 10000

unsigned int merge(unsigned int x, unsigned int y)
{
    return (x * (RANGE_MAX - RANGE_MIN + 1)) + y;
}

void split(unsigned int v, unsigned int &x, unsigned int &y)
{
    x = RANGE_MIN + (v / (RANGE_MAX - RANGE_MIN + 1));
    y = RANGE_MIN + (v % (RANGE_MAX - RANGE_MIN + 1));
}

결과는 정수 유형 카디널리티의 제곱근까지 범위의 단일 정수에 맞을 수 있습니다. 이것은 Stephan202의 일반적인 방법보다 약간 더 효율적입니다. 디코딩하는 것도 상당히 간단합니다. 초보자를 위해 제곱근이 필요하지 않습니다. :)


우연히 이것이 수레에 가능합니까?
Lukas


3

이것을 확인하십시오 : http://en.wikipedia.org/wiki/Pigeonhole_principle . A, B 및 C가 동일한 유형이면 수행 할 수 없습니다. A와 B가 16 비트 정수이고 C가 32 비트이면 쉬프팅을 사용할 수 있습니다.

해싱 알고리즘의 특성은 각 입력마다 고유 한 해시를 제공 할 수 없다는 것입니다.


2

다음은 @nawfal이 제공 한 방법을 기반으로 @DoctorJ 코드를 무제한 정수로 확장 한 것입니다. 인코딩 및 디코딩이 가능합니다. 일반 배열 및 numpy 배열에서 작동합니다.

#!/usr/bin/env python
from numbers import Integral    

def tuple_to_int(tup):
    """:Return: the unique non-negative integer encoding of a tuple of non-negative integers."""
    if len(tup) == 0:  # normally do if not tup, but doesn't work with np
        raise ValueError('Cannot encode empty tuple')
    if len(tup) == 1:
        x = tup[0]
        if not isinstance(x, Integral):
            raise ValueError('Can only encode integers')
        return x
    elif len(tup) == 2:
        # print("len=2")
        x, y = tuple_to_int(tup[0:1]), tuple_to_int(tup[1:2])  # Just to validate x and y

        X = 2 * x if x >= 0 else -2 * x - 1  # map x to positive integers
        Y = 2 * y if y >= 0 else -2 * y - 1  # map y to positive integers
        Z = (X * X + X + Y) if X >= Y else (X + Y * Y)  # encode

        # Map evens onto positives
        if (x >= 0 and y >= 0):
            return Z // 2
        elif (x < 0 and y >= 0 and X >= Y):
            return Z // 2
        elif (x < 0 and y < 0 and X < Y):
            return Z // 2
        # Map odds onto negative
        else:
            return (-Z - 1) // 2
    else:
        return tuple_to_int((tuple_to_int(tup[:2]),) + tuple(tup[2:]))  # ***speed up tuple(tup[2:])?***


def int_to_tuple(num, size=2):
    """:Return: the unique tuple of length `size` that encodes to `num`."""
    if not isinstance(num, Integral):
        raise ValueError('Can only encode integers (got {})'.format(num))
    if not isinstance(size, Integral) or size < 1:
        raise ValueError('Tuple is the wrong size ({})'.format(size))
    if size == 1:
        return (num,)
    elif size == 2:

        # Mapping onto positive integers
        Z = -2 * num - 1 if num < 0 else 2 * num

        # Reversing Pairing
        s = isqrt(Z)
        if Z - s * s < s:
            X, Y = Z - s * s, s
        else:
            X, Y = s, Z - s * s - s

        # Undoing mappint to positive integers
        x = (X + 1) // -2 if X % 2 else X // 2  # True if X not divisible by 2
        y = (Y + 1) // -2 if Y % 2 else Y // 2  # True if Y not divisible by 2

        return x, y

    else:
        x, y = int_to_tuple(num, 2)
        return int_to_tuple(x, size - 1) + (y,)


def isqrt(n):
    """":Return: the largest integer x for which x * x does not exceed n."""
    # Newton's method, via http://stackoverflow.com/a/15391420
    x = n
    y = (x + 1) // 2
    while y < x:
        x = y
        y = (x + n // x) // 2
    return x

2

더 간단한 것은 어떻습니까? 두 개의 숫자가 주어지면 A와 B는 str을 연결합니다 : 'A'+ ';' + 'B'. 그런 다음 출력을 hash (str)로 설정하십시오. 나는 이것이 수학적인 대답이 아니라 간단한 파이썬 (내장 해시 함수가 있음) 스크립트가 작동해야한다는 것을 알고 있습니다.


2
(8,11)과 (81,1)은 같은 숫자 811에 매핑됩니다
Leevi L

좋은 지적입니다. 중간에 기호를 추가하여이 문제를 해결할 수 있습니다. 따라서 (8, 11)의 경우 문자열 "8-11"을 해시하고 (81, 1)의 경우 문자열 "81-1"을 해시하십시오. 따라서 일반적으로 (A, B)의 경우 문자열 "AB"를 해시하십시오. (해키처럼 들리지만 작동해야합니다.)
Madhav Nakar

그것은 또한 두 개의 정수를 기호가있는 문자열이 아닌 새로운 정수에 매핑하는 것이기 때문에 잘못되었습니다
Leevi L

나는 수학적 관점이 아닌 CS 관점에서 왔습니다 (수학적 솔루션의 경우 위의 응답을 살펴보십시오). 정수로 바뀔 때 두 개의 정수를 가져 와서 문자열로 만듭니다. 본질적으로 네, 두 정수를 새로운 정수로 매핑합니다.
Madhav Nakar

1

당신이 제안하는 것은 불가능합니다. 항상 충돌이 발생합니다.

두 객체를 다른 단일 세트에 매핑하려면 매핑 된 세트의 최소 크기가 예상되는 조합 수 여야합니다.

32 비트 정수를 가정하면 2147483647 양의 정수가 있습니다. 순서가 중요하지 않고 반복되는 두 가지를 선택하면 2305843008139952128 조합이 생성됩니다. 이것은 32 비트 정수 세트에는 적합하지 않습니다.

그러나이 매핑을 61 비트로 맞출 수 있습니다. 64 비트 정수를 사용하는 것이 가장 쉽습니다. 높은 단어를 더 작은 정수로 설정하고 낮은 단어를 더 큰 정수로 설정하십시오.


1

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

0

두 개의 숫자 B와 C를 가지고 단일 숫자 A로 인코딩합시다.

A = B + C * N

어디

B = A % N = B

C = A / N = C


2
이 표현을 독특하게 만들기 위해 N을 어떻게 선택합니까? 이 문제를 해결하면 위의 답변과 어떻게 다른가요?
Prune

N은 B와 C보다 커야합니다.
Radoslav Stoyanov

0

양의 정수 A와 B가 주어지면 D = A에있는 자릿수, E = B에있는 자릿수 결과는 D, 0, E, 0, A 및 B의 연결 일 수 있습니다.

예 : A = 300, B = 12. D = 3, E = 2 결과 = 302030012. 이것은 0으로 시작하는 유일한 숫자가 0이라는 사실을 이용합니다.

Pro : 인코딩하기 쉽고, 해독하기 쉽고, 사람이 읽을 수 있으며, 유효 숫자를 먼저 비교할 수 있으며 계산없이 비교할 수 있으며 간단한 오류 검사가 가능합니다.

단점 : 결과의 크기가 문제입니다. 그러나 괜찮습니다. 어쨌든 컴퓨터에 무한 정수를 저장하는 이유는 무엇입니까?


0

첫 번째 숫자에 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 = 1023num_bnaximum 값으로 저장할 수 있습니다 2^12 - 1 = 4095.

숫자 A와 숫자 B의 값을 설정하려면

int bnum = nums_mapper.StoreAB(10/*value for a*/, 12 /*value from b*/);

이제 bnum모든 비트 (총 32 비트입니다. 64 비트를 사용하도록 코드를 수정할 수 있습니다)

int a = nums_mapper.GetNumA(bnum);

숫자 b를 얻으려면 :

int b = nums_mapper.GetNumB(bnum);

편집 : bnum클래스 안에 저장할 수 있습니다. 내 자신의 요구 때문에 코드를 공유하고 도움이되기를 바랍니다.

소스를 가져 주셔서 감사합니다 : https://www.geeksforgeeks.org/extract-k-bits-given-position-number/ 비트를 추출하는 기능 mouviciel과이 게시물의 답변에 감사드립니다 . 이것을 소스로 사용하면 더 고급 솔루션을 찾을 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.