c++ - 快速将 '0 1 1 0 1'格式的字符串转成bitset

标签 c++ performance c++11 bitset std-bitset

如何快速将一串由空格分隔的 1 和 0 转换为 bitset

存在一个构造函数,用于从不以空格分隔的字符串初始化 bitset,一个用于将 bitset 初始化为全 0 或 1,另一个用于从整数。 在我的头脑中,我可以想到三种方法:

  • 从字符串中删除空格并将其传递给构造函数
  • 将二进制转换为整数并将其传递给构造函数
  • 将所有值初始化为零并根据for循环中的字符串更改每个位的值

位数是24位,每个字符串正好有24位,不多也不少。

编辑: Here是我用来测试性能的代码,here是方法一和方法二的代码。在我的机器上,方法 1 需要 3 毫秒,方法 3 需要 14 毫秒。

编辑 2: 我使用 -O3 -o -g --std=c++11 是我的编译器设置。我使用了 gcc clang。

最佳答案

通过相应地设置每一位来转换(不改变输入字符串)到无符号整数:

#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”之外的任何字符(像“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++ 4.8.4 与 g++ -std=c++11 -O3 显示:

to_bitset从字符串中删除空格/构造位集 快大约 3 倍。

关于c++ - 快速将 '0 1 1 0 1'格式的字符串转成bitset,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38130979/

相关文章:

c# - 在 IEnumerable 上调用 Count 是否会迭代整个集合?

javascript - 将事件委托(delegate)给 Backbone.js 中的 subview

C++ 返回函数 lock_guard

c++ - 在 C++11/14 中说 "foo not in {bar, baz}"的漂亮方式

c++ - sqlite:检查读写器锁

c++ - 使用 Qt C++ 在 Linux 中获取通过 USB 连接的 ESC/POS 打印机的状态

c++ - MFC 中的抽象基类是否需要 DECLARE_DYNAMIC?

linux - Linux USB 批量传输内核驱动程序和硬件环回的性能非常差(~0.4MB/s)

c++ - 我需要在这里显式调用析构函数吗?

c++ - 为什么我不能分配这个指针?