2014-03-27 6 views
0

세 개의 식별자가 있으면 단일 32 비트 값으로 결합하십시오.3 개의 32 비트 식별자를 하나의 32 비트 식별자로 결합합니까?

첫 번째 식별자는 (2^8) -1 개의 다른 값을 가질 수 있습니다. 유사하게 두 번째 (2^8) -1과 세 번째 (2^10) -1. 따라서 모든 종류의 식별자의 총 개수는 (2^32) -1을 초과하지 않습니다.

예 용액 맵을 가질 수 있었다 :

  • 키를 32 비트
  • 값 : 8 (또는 10) 비트.

값은 0에서 시작하여 새 식별자가 제공 될 때마다 증가합니다.

더 잘 할 수 있습니까? (3 개지도 대신)이 솔루션에 문제가 있습니까? 명확히


는 식별자 범위 < 0, 32^2)에서 어떤 값을 보유 할 수있다. 주어진 유일한 정보는 그것들의 총 수가 (2^8) -1 (또는 10)을 초과하지 않는다는 것입니다.

식별자의 값은 동일 할 수 있습니다 (완전히 임의적입니다). OS가 힙 할당 메모리 (예 : 포인터를 식별자로 사용)에 제공 한 임의성 소스 메모리 주소를 고려하십시오. 이것이 x64 시스템에서 다르게 작동한다는 것을 알았지 만, 일반적인 문제 해결 방법이이 특정 시스템과 유사하기를 바랍니다.

이것은 간단한 비트 시프트가 문제가되지 않는다는 것을 의미합니다.

+0

왜 3 비트 필드를 사용하지 않는가? – harold

+0

''encoded = ((b10 * 256) + b8_1) * 256 + b8_2' 그리고 그 반대 방향으로 디코딩을 할 수 없습니까? 꽤 효율적이어야합니다. –

+1

여기에 약간의 설명이 필요합니다. 3 개의 식별자가 숫자입니까? 그들은 별개입니까?그들이 취할 수있는 가치의 범위를 조금 더 자세하게 설명 할 수 있습니까? (MichaelS의 답변에서 토론을 참조하십시오). 당신은 미리 다른 값들을 모두 알고 있습니까? – waTeim

답변

1

이 같은 것을 시도해 볼 수도 있습니다 : -

#include <map> 
#include <iostream> 

class CombinedIdentifier 
{ 
public: 
    CombinedIdentifier (unsigned id1, unsigned id2, unsigned id3) 
    { 
     m_id [0] = id1; 
     m_id [1] = id2; 
     m_id [2] = id3; 
    } 

    // version to throw exception on ID not found 
    static CombinedIdentifier GetIdentifier (unsigned int id) 
    { 
     // search m_store for a value = id 
     // if found, get key and return it 
     // else....throw an exception->id not found 
    } 

    // version to return found/not found instead of throwing an exception 
    static bool GetIdentifier (unsigned int id, CombinedIdentifier &out) 
    { 
     // search m_store for a value = id 
     // if found, get key and save it to 'out' and return true 
     // else....return false 
    } 

    int operator [] (int index) { return m_id [index]; } 

    bool operator < (const CombinedIdentifier &rhs) const 
    { 
     return m_id [0] < rhs.m_id [0] ? true : 
       m_id [1] < rhs.m_id [1] ? true : 
       m_id [2] < rhs.m_id [2]; 
    } 

    bool operator == (const CombinedIdentifier &rhs) const 
    { 
     return m_id [0] == rhs.m_id [0] && 
       m_id [1] == rhs.m_id [1] && 
       m_id [2] == rhs.m_id [2]; 
    } 

    bool operator != (const CombinedIdentifier &rhs) const 
    { 
     return !operator == (rhs); 
    } 

    int GetID() 
    { 
     int 
      id; 

     std::map <CombinedIdentifier, int>::iterator 
      item = m_store.find (*this); 

     if (item == m_store.end()) 
     { 
      id = m_store.size() + 1; 
      m_store [*this] = id; 
     } 
     else 
     { 
      id = item->second; 
     }   

     return id; 
    } 

private: 
    int 
     m_id [3]; 

    static std::map <CombinedIdentifier, int> 
     m_store; 
}; 

std::map <CombinedIdentifier, int> 
    CombinedIdentifier::m_store; 

int main() 
{ 
    CombinedIdentifier 
     id1 (2, 4, 10), 
     id2 (9, 14, 1230), 
     id3 (4, 1, 14560), 
     id4 (9, 14, 1230); 

    std::cout << "id1 = " << id1.GetID() << std::endl; 
    std::cout << "id2 = " << id2.GetID() << std::endl; 
    std::cout << "id3 = " << id3.GetID() << std::endl; 
    std::cout << "id4 = " << id4.GetID() << std::endl; 
} 
+0

화려하고 깨끗합니다 (세 개의 별도 맵보다 훨씬 깨끗합니다). 쉽게 액세스 할 수 있습니다. 이 답변에 감사드립니다. – hauron

+0

기본적으로 3 개의 숫자를 배열 (96 비트 연속 메모리)로 저장하고 있습니까? – justhalf

+0

@justhalf : 네, 기본 레벨에서 그렇습니다. 그러나 OP는 그 수량 이외의 ID에 대한 제약 조건을 지정하지 않았습니다. 따라서 'max (ID)'가 더 큰 경우 비트 패킹으로 인해 데이터가 손실 될 수 있습니다 사용할 수있는 비트보다 이 방법은 세 ID를 모두 보존합니다. 더 중요한 것은 3 개의 ID는 하나의 'int'를 사용하여 색인을 생성 할 수 있지만, 단 하나의 ID를 3 개의 ID로 쉽게 변환 할 수있는 방법이 있어야한다는 것을 알았습니다. – Skizz

1

비트 이동 및 안전하지 않은 코드로이 작업을 수행 할 수 있습니다. SO를에 기사가

: What are bitwise shift (bit-shift) operators and how do they work?

그런 다음 당신은 당신의 세 가지 값을 전체 32 비트 범위를 사용할 수는

---- 8 비트 ---- | ---- 8 비트 ---- | ---- 10 비트 ---- | ----되지 않는 6 비트 ----

int result = firstValue << (8 + 10 + 6); 
result += secondValue << (10 + 6); 
result += thirdValue << 6; 
+0

문제를 잘못 이해했습니다. 2 개의 8 비트 숫자와 10 비트 숫자를 결합하는 것이 아닙니다. 255,255,1023 개의 다른 (아마 임의의) 값을 가질 수있는 3 32 비트 숫자를 결합하는 것. – waTeim

+0

이 질문은 각 단어의 더 낮은 'k'비트 만이 2^k - 1 값 중 하나를 지정하는 데 사용된다는 것을 암시하는 것처럼 보입니다. – chepner

+1

실제로는 제목이 반대입니다. 2^8 - 1 순차 값을 말한다면, 나는 동의한다. 당신이 너무 많이 읽고 있다고 생각합니다. 그는 숫자가 아니라지도에 관해 이야기하고있었습니다. 그렇지 않으면, 이것은 모두 사소한 것입니다. – waTeim

1

난 당신이 a Perfect Hash Function의 사용을 만들 수 있다고 생각. 특히, Pearson Hashing에 해당 기사가 제공된 링크가 적절하다고 판단됩니다. 포함 된 C 프로그램의 두 번째 기사를 잘라내어 붙여 넣을 수도 있습니다. 단, 출력은 32 비트가 아닌 64 비트입니다. 당신이

for (j=0; j<4; j++) { 
    // standard Pearson hash (output is h) 

for (j=0; j<8; j++) { 
    // standard Pearson hash (output is h) 

약간 수정한다면 당신은 당신이 필요로 할 것이다.

+0

그러나 나는 이것을 좋아하지만 Skizz의보다 단순한 접근법을 사용할 것입니다. 명확한 이유는 코드화 될 것이고, 내가 그것을 유지하는 유일한 사람이되지는 않을 것입니다. 답변과 링크를 가져 주셔서 감사합니다. – hauron

+0

또 다른 문제. 이 솔루션은 가능한 입력에 대한 사전 지식없이 완벽한 해싱을 제공하지 않습니다. 충돌은 불행히도 문제입니다. 좋은면은 공유 된 코드/변수가 아닌 쉬운 멀티 스레딩 일 것입니다. 선택한 솔루션은 어떤 종류의 뮤텍스가 필요합니다 ... – hauron