2009-10-16 3 views
1

C++에서 int와 doubles (공칭 및 실수 값 데이터를 나타내는) 컬렉션을 저장해야합니다. 나는 분명히 그들 모두를 std::vector<double>에 저장할 수 있지만 이것은 약간 잘못 생각하고 미학적 보너스 포인트를 얻지 못합니다.복소수와 정수의 혼합 된 컬렉션을 저장하는 가장 효율적인 방법

또한 다형성을 기반으로 무언가를 만들 수도 있지만 정말 효율적인 컬렉션이 필요합니다. 컬렉션에 데이터를 저장하고 검색하는 작업은 가능한 한 빨리해야합니다. 그런 해결책이 최대한 효율적인지 판단하기가 어렵습니다.

나는 또한 boost::variant을 발견했으며, 도움이 될 것입니다.

추가 정보 : 컬렉션의 항목 수가 작아서 (< 100) 컬렉션을 초기화 할 때 알 수 있습니다.

요약 : 나는 분명히 수많은 방법으로이 문제를 해결할 수 있지만 (i) 효율성이 정말 중요하고 (ii) 다소 훌륭한 코드를 작성하려고 할 때 어떤 것이 좋은 해결책이 될지 확신 할 수 없습니다. 내 최선의 내기는 무엇입니까?

편집 추가 정보 : 컬렉션은 더 큰 데이터 세트의 '행'을 나타내며 그 요소는 특정 '열'의 값을 나타냅니다. 행의 특성이 알려 지므로 어떤 위치에 어떤 종류의 데이터가 저장되어 있는지 알 수 있습니다. 필자가 말하고있는 '효율성'은 값의 빠른 설정이 중요하기는하지만 주로 특정 열의 int/double 값을 검색하는 효율성입니다. 가능한 한 빨리 검색해야하는 데이터에서 작동하는 몇 가지 기능이 있습니다. 예 : 좀 더 생각하고 지금까지 제안을 읽은 후

typedef std::vector<double> Row; 

void doubleFun(Row const &row) 
{ 
    // Function knows there's always a double at index 0 
    double value = row[0]; 
    ... 
} 

void integerFun(Row const &row) 
{ 
    // Function knows there's always an integer at index 1 
    int value = row[1]; 
    ... 
} 

, 그냥 두 개의 벡터에서 INT 열 두 번 열을 저장하는 고체 해결책이 보인다. 그런 다음 컬렉션 은 함수가 사용할 수있는 명목 데이터와 실제 데이터를 검색하기 위해 두 개의 다른 멤버를 정의 할 수 있습니다.

그냥 vector<double>으로 저장하는 것도 괜찮습니다.하지만 double과 int 사이의 변환이 얼마나 빠른지 (아마도 꽤 인상적입니다)에 달려 있습니다.

처음에는 약간 불명 한 점에 대해 사과드립니다. 더 명확하고 이제는 문제에 대해 좀 더 생각해 볼 수 있기를 바랍니다.

+0

최상의 솔루션을 알기에 충분한 정보를 제공하지 못했습니다. - 컬렉션의 속성은 무엇입니까? 중복이 허용됩니까? 순서가 중요합니까? 정렬해야합니까? 데이터 유형을 보존해야합니까, 아니면 10.0 (double)을 삽입하고 10 (int)을 검색 할 수 있습니까? – Tom

+0

또한 최적화하려는 효율성 측정 기준은 무엇입니까? 전체 공간? 삽입 시간? 무작위 액세스 조회 시간? 반복 시간? – Tom

+0

추가 정보로 업데이트되었습니다. 처음에는 너무 명확하지 않아서 죄송합니다. 지금은 더 좋을 것 같네요. –

답변

5

컨테이너의 중요한 부분을 주문하고 있습니까?

그렇지 않은 경우

class MyContainer 
{ 
    std::vector<double> doubles; 
    std::vector<int> ints; 

    push(double value) { doubles.push_back(value); } 
    push(int value) { ints.push_back(value); } 

    .... 
}; 

반복자 부분 약간 난이도가 될 수있다 (전체 컨테이너를 검색하기 위해) ...

+0

업데이트 된 요구 사항이 주어지면 이는 가장 현명한 것으로 보입니다. – Tom

3

공용체 형식을 사용하여 벡터에서 사용할 수 있습니다. 그러나이 경우 벡터의 어떤 요소를 int로 처리해야하는지, 어떤 요소를 double로 처리해야 하는지를 알 수있는 방법이 필요합니다. 어떤 것이 int이고 어떤 것이 double인지 추적하려면 비트셋 또는 그와 유사한 것을 사용할 수 있습니다.

목표가 무거운 부동 소수점 계산을 피하는 것인지 확실하지 않습니다. 그렇다면 비트 세트가 더 효율적일 수 있습니다. 그렇지 않고 정확한 int 정밀도가 중요하지 않은 경우 두 가지 모두로 저장할 수 있습니다.

#include <vector> 
#include <bitset> 

union di 
{ 
    double d; 
    int i; 
}; 


int main(int argc, char* argv[]) 
{ 

    std::bitset<2> bitsetInts; 

    std::vector<di> v; 
    di e1; 
    e1.d = 3.9; 
    v.push_back(e1); 

    di e2; 
    e2.i = 3; 
    bitsetInts.set(1); 
    v.push_back(e2); 

    return 0; 
} 
+0

최대 크기가 고정되어 있다면 이것은 내가 생각한 것과 똑같습니다. – Tom

1

컴파일 타임에 유형을 알고있는 경우 사용할 수있는 부스트 튜플이 있습니다. 그러나 항목 수가 적 으면 100 바이트를 낭비하는 것이 효율적이지 않아야합니다.

3

나는 boost::variant 솔루션으로 가고 싶습니다. 귀하의 요구에 완벽하게 부합합니다.

5

이중 벡터를 직접 사용하지 않는 이유는 무엇입니까? 정수는 정밀도를 잃지 않고 두 배로 변환 될 수 있기 때문에 가장 간단하고 효율적인 솔루션입니다.

정상적인 값과 실수 값의 차이를 만드는 방법은 무엇입니까 (그리고 궁금한 점을 모르겠습니다). 문제는 선택할 수있는 모든 솔루션에 열려 있습니다.

+0

사실, 이제 10.0은 double 또는 정수입니까? – gbjbaanb

+0

진짜 질문은 "10.0은 정상인가 실제 가치인가?"입니다. 그러나 내가 대답 할 때 말했듯이, 나는 충분한 정보가 없습니다. 변종을 사용하는 경우에도 동일한 질문을 할 수 있습니다. –

+0

@ Cătălin 부스트 :: 변형은 저장 유형입니다. 방문자를 사용하여 올바른 유형을 검색 할 수 있습니다. – TimW

관련 문제