2016-06-30 2 views
0

공백으로 구분 된 1과 0의 문자열을 신속하게 bitset으로 변환 할 수 있습니까?'0 1 1 0 1'형식의 문자열을 비트 셋으로 신속하게 변환

공백으로 구분되지 않은 문자열에서 bitset을 초기화하는 생성자가 있습니다. 하나는 bitset을 모두 0 또는 1로 초기화하고 하나는 정수에서 초기화합니다. 내 머리 위로 떨어져 , 나는 세 가지 방법을 생각할 수 있습니다

  • 문자열에서 공백을 제거하고 정수로 바이너리 변환 생성자
  • 에 전달하고 생성자
  • 에 전달
  • 하기에 문자열에 따른 모든 값을 0으로 초기화하고, 각 비트의 값을 변경하기위한 루프

비트 수는 24이며, 각 캐릭터가 더 적은 더 정확히 24 비트, 없다.

편집 :Here은 성능 테스트에 사용하는 코드이고 here은 방법 1과 2의 코드입니다. 내 컴퓨터에서 방법 1은 3 밀리 초가 걸리고 방법 3은 14 밀리 초가 걸립니다.

편집 2 :-O3 -o -g --std=c++11은 제 컴파일러 설정입니다. 나는 gcc clang을 사용했다.

+6

첫 번째 옵션을 사용합니다. –

+0

나는 모든 공백을 제거하고, 옵션 1을 사용한다. –

+0

나는 여전히 언급 된 3 가지 이외의 방법을 찾고있다. 내 테스트에서 방법 1은 방법 3보다 4.67 배 빠릅니다. –

답변

1

따라서 각 비트를 설정하여 부호없는 정수로 전환 (입력 문자열 돌연변이 생략) :

#include <bitset> 
constexpr unsigned long long 
extract_bits(const char* ptr, unsigned long long accumulator) { 
    return (*ptr == 0) 
     ? accumulator 
     : extract_bits(ptr + 1, (*ptr == '1') 
      ? accumulator << 1u | 1u 
      : (*ptr == '0') 
       ? accumulator << 1 
       : accumulator); 
} 

template <unsigned N> 
constexpr std::bitset<N> 
to_bitset(const char* ptr) { 
    return std::bitset<N>(extract_bits(ptr, 0)); 
} 

#include <iostream> 
int main() 
{ 
    constexpr auto b = to_bitset<24>("0 0 1 1 0 0 1 1 0 0 1 1 1 1 0 0 1 1 0 0 1 1 0 0"); 
    std::cout << b << '\n'; 
    return 0; 
} 

참고 : 변환과 같은 '0'과 '1'조용히 (A 문자열 이외의 문자는 무시 " 01-01 "도 유효합니다).

된 문자열로부터 상기 전환 타이밍과 공간 소거 방법 :

#include <algorithm> 
#include <cctype> 
#include <cstring> 
#include <chrono> 
#include <iostream> 
#include <random> 

using namespace std::chrono; 

void print_duration(const char* what, const system_clock::time_point& start, const system_clock::time_point& stop) { 
    auto duration = duration_cast<microseconds>(stop - start); 
    std::cout << what << ": " << duration.count() << std::endl; 
} 

volatile unsigned long long result; 
int main() 
{ 
    std::string str = "0 0 1 1 0 0 1 1 0 0 1 1 1 1 0 0 1 1 0 0 1 1 0 0"; 
    std::vector<std::string> strings(1000, str); 
    std::random_device random_device; 
    std::mt19937 random_generator(random_device()); 
    for(auto& str : strings) { 
     std::shuffle(str.begin(), str.end(), random_generator); 
    } 

    // Non mutating to_bitset 
    { 
     auto start = system_clock::now(); 
     for(const auto& str : strings) { 
      auto b = to_bitset<24>(str.c_str()); 
      result = b.to_ullong(); 
     } 
     auto stop = system_clock::now(); 
     print_duration("to_bitset", start, stop); 
    } 
    // Erasing spaces 
    { 
     auto start = system_clock::now(); 
     for(auto& str : strings) { 
      str.erase(std::remove_if(str.begin(), str.end(), ::isspace), str.end()); 
      auto b = std::bitset<24>(str); 
      result = b.to_ullong(); 
     } 
     auto stop = system_clock::now(); 
     print_duration("str.erase", start, stop); 
    } 
    return 0; 
} 

g g과 4.8.4 ++ ++ ++ -std = C 11 -03 보여준다

to_bitset 약 3 배 erasing spaces from a string/constructing a bitset보다 빠릅니다.

+0

질문은 얼마나 빠릅니까 –

+0

시간을 보내고 보지 않으시겠습니까? 또한, 나는 문자열에서 24 개의 공백을 제거하는 것을 최적화하는 것을 시도함으로써 얻는 것이 무엇이든 의심하지 않는다. – PaulMcKenzie

+1

@PaulMcKenzie 루프가 수백만 번 반복되는 경우가 아닙니다. –