무한 선형 이진 저장소가 있다고 가정 할 때 0에서 무한대까지의 정수를 나타내는 좋은 스키마?


10

무한 선형 저장소에 대한 액세스를 가정하여 제한없이 0으로 시작하는 정수를 나타내는 스키마를 원합니다.

다음은 0에서 255까지의 숫자를 나타낼 수있는 스키마입니다.

스토리지의 첫 번째 바이트 (주소 0)를 사용하여 정수를 저장하십시오.

이제 255보다 큰 숫자를 나타내고 싶다고 가정 해 봅시다. 물론, 정수를 나타 내기 위해 1 바이트 이상을 사용할 수 있지만, 고정 된 숫자라면 결국에는 표현할 수 없을 정도로 큰 정수가 있습니다. 원래 스키마.

다음은 작업을 수행 할 수 있어야하는 다른 스키마이지만 효율적이지는 않습니다.

일종의 고유 한 "end of number"바이트를 사용하고 이전의 모든 바이트를 사용하여 숫자를 나타냅니다. 분명히, "숫자 끝"바이트는 숫자 표현의 어느 곳에서나 사용될 수 없지만, 이것은 기본 -256 대신에 기본 -255 번호 시스템을 사용함으로써 달성 될 수 있습니다.

그러나 속도가 느리고 비효율적입니다. 낮은 값과 스케일로 더 잘 수행되는 더 나은 것을 원합니다.

기본적으로 UUID 시스템입니다. 이론적으로 몇 년, 수천 년, 수백만 년 동안 재 설계하지 않고도 사용할 수있는 빠른 성능의 UUID 시스템을 만들 수 있는지 알고 싶습니다.


1
무한대로 (개구 식에서와 같이) 또는 수백만 년 동안 (폐쇄에서와 같이) 확장 할 수있는 것을 원하십니까? 두 가지 요구 사항은 (분명히) 완전히 다릅니다. 64 비트 컴퓨터에서 2 개의 보완 기능 은 수백만 년 동안 확장 될 것 입니다.
user16764

1
@ user16764, 단일 64 비트 정수 변수를 의미합니까? 600 만 명이 초당 1 백만 UUID를 소비하는 경우 한 달 이상 지속될 수 없습니다.
Dmitri Shuralyov 님이

1
그리고 128 비트 시스템에서 얼마나 오래 걸립니까?
user16764

2
임의로 큰 양의 정수에 대해 사전 순으로 정렬 된 ASCII 표현을 제공하는 RFC 2550 의 아이디어는 이에 적합 할 수 있습니다. 궁극적으로 base-10 세그먼트의 길이를 인코딩하는 base-26 세그먼트의 길이를 인코딩하는 단항 세그먼트로 분류됩니다. 후자의 두베이스는 스키마 표현의 기본 요소보다 ASCII 표현과 관련이 있습니다.
Random832

1
128 비트 숫자를 순차적으로 생성한다고 가정합니다. 모든 사람에게 페타 플롭 컴퓨터를 제공하여 모든 컴퓨터의 계산 용량을 상한으로 설정하면이 숫자가 떨어지기까지 9 백만 년이 걸립니다. 반면에 모든 사람이 무작위로 6 억 개의 128 비트 숫자를 생성한다면, 1 개의 복제본을 생성 할 확률은 50 %입니다. 당신에게 충분합니까? ( en.wikipedia.org/wiki/Universally_unique_identifier ) 그렇지 않은 경우 256 비트를 사용하면이 두 숫자에 2 ^ 128 = 3.4 * 10 ^ 38이 곱해집니다.
Alex ten Brink

답변:


13

내가 사용한 접근법 : 선행 1 비트 수를 계산하십시오 n. 숫자의 크기는 2 ^ n 바이트 (앞의 1 비트 포함)입니다. 첫 0 비트 이후의 비트를 정수로 취하고 2 ^ (n-1) 바이트의이 인코딩을 사용하여 숫자로 표시 할 수있는 최대 값 (1을 더한 값)을 추가하십시오.

그러므로,

                  0 = 0b00000000
                   ...
                127 = 0b01111111
                128 = 0b1000000000000000
                   ...
              16511 = 0b1011111111111111
              16512 = 0b11000000000000000000000000000000
                   ...
          536887423 = 0b11011111111111111111111111111111
          536887424 = 0b1110000000000000000000000000000000000000000000000000000000000000
                   ...
1152921505143734399 = 0b1110111111111111111111111111111111111111111111111111111111111111
1152921505143734400 = 0b111100000000000000000000000000000000000000000000 ...

이 체계를 사용하면 음수가 아닌 값을 정확히 한 가지 방식으로 나타낼 수 있습니다.

(동일하게 선행 0 비트 수를 사용했습니다.)


1
나는 많은 답변이 유익하고 유익하다고 생각하기 때문에 어떤 답변을 받아 들인 것으로 표시할지 알아내는 것이 어려웠다. 그러나 나는 이것이 내가 묻는 질문에 가장 적합하다고 생각합니다 (아마도 내가 생각했던 근본적인 질문이 아닐 수도 있습니다.
Dmitri Shuralyov

2
예제 구현 및 디자인 고려 사항과 함께 보다 자세한 기사 를 작성했습니다.
retracile

10

당신이하려는 일에 근거한 많은 이론이 있습니다. 범용 코드 에 대한 위키 페이지를 살펴보십시오. 정수 인코딩 방법의 전체 목록이 있습니다 (일부는 실제로 실제로 사용됨).

데이터 압축에서 정수에 대한 범용 코드는 양의 정수를 이진 코드 워드에 매핑하는 접두사 코드입니다.

또는 처음 8 바이트를 사용하여 숫자 길이를 일부 단위 (대부분 바이트)로 저장 한 다음 데이터 바이트를 넣을 수 있습니다. 구현하기가 쉽지만 적은 수의 경우 비효율적입니다. 그리고 인류가 사용할 수있는 모든 데이터 드라이브를 채울만큼 정수를 코딩 할 수 있습니다 :)


그것에 대해 감사합니다, 그것은 매우 흥미 롭습니다. 나는 이것을 대답으로 인정하고 싶었지만 2 위를 차지했다. 이것은 이론적 인 관점 인 IMO의 매우 좋은 대답입니다.
Dmitri Shuralyov가

4

선행 1의 수에 첫 번째 0을 더한 경우 숫자 크기 (numSize)의 크기 (sizeSize)를 비트 단위로 지정하십시오. numSize는 크기 비트를 포함하여 숫자 표현의 크기를 바이트 단위로 제공하는 이진수입니다. 나머지 비트는 이진수의 숫자 (숫자)입니다. 양의 정수 체계의 경우 샘플 예제 번호는 다음과 같습니다.

Number              sizeSize  numSize    num
63:                 0 (1)     1 (1)      111111
1048575:            10 (2)    11 (3)     1111 11111111 11111111
1125899906842623:   110 (3)   111 (7)    11 11111111 11111111 11111111 11111111 11111111 11111111
5.19.. e+33:        1110 (4)  1111 (15)  11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111

4

어떻습니까 : 길이는 1 바이트, 숫자는 n 바이트입니다 (먼저 중요 바이트). 이전 길이가 255 인 경우 length + number를 반복하십시오.

이것은 임의로 많은 수를 허용하지만 여전히 다루기 쉽고 너무 많은 메모리를 낭비하지 않습니다.


fNek : 상한이 없습니다. 예를 들어, 숫자에 513 바이트가 필요한 경우 바이트 순서는 [255, b0, ..., b255,255, b256, ..., b511,2, b512, b513]
user281377

죄송합니다. 더 자세히 읽는 법을 배워야합니다.
fNek

3

각 바이트에서 7 비트 만 사용하고 8 번째 비트를 사용하여 따라야 할 다른 바이트가 있는지 여부를 나타내십시오. 따라서 1-127은 1 바이트이고 128은 0x80 0x01 등으로 표시됩니다.


1
이 방식은 8 비트마다 128 개의 값만 인코딩하는데, 이는 실제로 질문자가 제안한 두 번째 인코딩 방식보다 공간 효율이 낮으며, 여기서 8 비트마다 255 개의 값이 인코딩됩니다. 두 가지 체계 모두 저장해야 할 스토리지 용량을 확인하려면 정수를 읽어야한다는 사실로 인해 어려움을 겪고 있습니다.
Mark Booth

3
따라서 숫자를 두 번 스캔하여 복사해야합니까? 무한히 큰 숫자를 기다릴 수 있으면 두 번 기다릴 수 있습니다.
Russell Borogove

매우 신중하게 지정하지는 않았지만 가능한 한 효율적으로 수행되는 솔루션을 찾고 있습니다 (요구 사항과 단순히 일치하는 솔루션 대신; 이미 내 질문에 잠재적으로 비효율적 인 답변 중 하나를 설명했습니다).
Dmitri Shuralyov

3

UUID 시스템은 유한 한 (그러나 큰) 우주에서 유한 한 (그러나 큰) 컴퓨팅 성능을 기반으로합니다. UUID의 수는 우주의 입자 수와 같이 터무니없이 큰 것들과 비교할 때도 많습니다. 그러나 고정 비트 수에 관계없이 UUID의 수는 무한대에 비해 적습니다.

0xFFFF를 사용하여 숫자 끝 플래그를 나타내는 문제는 숫자가 클 때 숫자 인코딩의 효율성이 떨어진다는 것입니다. 그러나 UUID 구성표로 인해이 문제가 더욱 악화되는 것 같습니다. 256 바이트 중 하나를 건너 뛰는 대신 이제 전체 UUID 공간이 낭비되었습니다. 공간이 아닌 계산 / 인식의 효율성은 이론적 인 컴퓨터에 달려 있습니다 (무한대에 대해 이야기하고 있다면 가정합니다). 테이프 및 유한 상태 컨트롤러가있는 TM의 경우 UUID 구성표를 효율적으로 확장 할 수 없습니다 (기본적으로 펌핑 보조 장치는 고정 비트 길이 엔드 마커를 넘어 효율적으로 이동하지 못하게합니다). 유한 상태 컨트롤러를 가정하지 않으면 적용되지 않을 수 있지만 디코딩 / 인식 프로세스에서 비트의 위치를 ​​고려해야합니다.

256 바이트 중 1 바이트보다 더 나은 효율성을 원한다면 UUID 체계에 1 비트 길이를 사용하십시오. 비효율적으로 2 ^ 비트 길이 중 1입니다.

그러나 다른 인코딩 체계가 있습니다. 구분 기호가있는 바이트 인코딩은 구현하기가 가장 쉽습니다.


2

바이트 배열 (또는 int 또는 long)과 숫자의 길이를 나타내는 길이 필드를 갖는 것이 좋습니다.

이것은 대략 Java의 BigInteger가 사용하는 접근 방식 입니다. 이것으로부터 가능한 주소 공간은 방대합니다-우주의 모든 개별 원자에 다른 UUID를 제공하기에 충분합니다 :-)

다른 이유가 없다면 BigInteger를 직접 사용하거나 다른 언어로 사용하는 것이 좋습니다. 큰 숫자 휠을 재발 명할 필요가 없습니다 ....


필드 수에 제한이 없으면 배열의 길이를 인코딩 할 수 없습니다.
Slawek

가능한 경우 주어진 문제에 대해 기존 솔루션 (특히 전문적인 조사를 거친 솔루션)을 사용하는 것이 바람직하다는 데 동의합니다. 감사.
Dmitri Shuralyov

@Slawek : true, 그러나 유스 케이스에 대해 OP가 설명하는 (즉, UUID) BigInteger는 사실상 무한합니다. 어쨌든 유한 한 크기의 메모리가있는 컴퓨터에서는 무한 정보를 인코딩 할 수 없으므로 BigInteger는 달성 할 수있는 다른 것만 큼 좋습니다.
mikera

2

우선, 비교적 모호하고 추상적 인 질문에 큰 답변을 주신 모든 분들께 감사드립니다.

다른 답변에 대해 생각한 후에 생각했던 잠재적 인 답변에 기여하고 싶습니다. 질문에 대한 직접적인 답변은 아니지만 관련이 있습니다.

일부 사람들이 지적했듯이 64/128/256 비트 크기의 정수를 사용하면 UUID에 대한 공간이 이미 넓습니다. 분명히 그것은 무한하지 않지만 ...

64 비트가 충분하지 않을 때까지 또는 고정 된 크기의 int (예 : 64 비트 시작)를 사용하는 것이 좋습니다. 그런 다음 UUID의 모든 이전 인스턴스에 액세스 할 수 있다고 가정하면 모두 128 비트 정수로 업그레이드하고 고정 크기의 정수로 사용하십시오.

시스템이 서비스 일시 중지 / 중단을 허용하고 이러한 "재 구축"작업이 자주 발생하지 않기 때문에 이점 (매우 단순하고 빠르고 구현하기 쉬운 시스템)이 단점을 초과 할 수 있습니다 (이전에 할당 된 모든 정수를 재 구축해야 함) 새로운 정수 비트 크기로).

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