在我的项目,我用巨大的一套短字符串的ASCII 7位和必须处理(存储,比较,搜索等),这些字符串以最大性能。 基本上,我建立uint64_t中类型的一些索引阵列,并且每个元素存储一个字的9个字符,并使用该索引作为数字元件,用于任何字符串比较操作。 当前执行工作的快速,但可能这是可能的,如果你会去改善它一点..
此函数向上转换为9个初始字符uint64_t中值 - 该数字的任何比较的等效标准“的strcmp”的功能。
#include <cstdint>
#include <iostream>
uint64_t cnv(const char* str, size_t len)
{
uint64_t res = 0;
switch (len)
{
default:
case 9: res = str[8];
case 8: res |= uint64_t(str[7]) << 7;
case 7: res |= uint64_t(str[6]) << 14;
case 6: res |= uint64_t(str[5]) << 21;
case 5: res |= uint64_t(str[4]) << 28;
case 4: res |= uint64_t(str[3]) << 35;
case 3: res |= uint64_t(str[2]) << 42;
case 2: res |= uint64_t(str[1]) << 49;
case 1: res |= uint64_t(str[0]) << 56;
case 0: break;
}
return res;
}
int main()
{
uint64_t v0 = cnv("000", 3);
uint64_t v1 = cnv("0000000", 7);
std::cout << (v1 < v0);
}
您可能会加载8个字节的原始字符串的一次比凝结他们得到的整内(和扭转他们,如果你的机器有一个小端数表示)。
#include <iostream>
uint64_t ascii2ulong (const char *s, int len)
{
uint64_t i = (*(uint64_t*)s);
if (len < 8) i &= ((1UL << (len<<3))-1);
#ifndef BIG_ENDIAN
i = (i&0x007f007f007f007fUL) | ((i & 0x7f007f007f007f00) >> 1);
i = (i&0x00003fff00003fffUL) | ((i & 0x3fff00003fff0000) >> 2);
i = ((i&0x000000000fffffffUL) << 7) | ((i & 0x0fffffff00000000) << (7-4));
// Note: Previous line: an additional left shift of 7 is applied
// to make room for s[8] character
#else
i = ((i&0x007f007f007f007fUL) << 7) | ((i & 0x7f007f007f007f00) >> 8);
i = ((i&0x00003fff00003fffUL) << 14) | ((i & 0x3fff00003fff0000) >> 16);
i = ((i&0x000000000fffffffUL) << (28+7)) | ((i & 0x0fffffff00000000) >> (32-7));
#endif
if (len > 8) i |= ((uint64_t)s[8]);
return i;
}
//Test
std::string ulong2str(uint64_t compressed) {
std::string s;
for (int i = 56; i >= 0; i-=7)
if (char nxt=(compressed>>i)&0x7f) s+= nxt;
return s;
}
int main() {
std::cout << ulong2str(ascii2ulong("ABCDEFGHI", 9))<<std::endl;
std::cout << ulong2str(ascii2ulong("ABCDE", 5))<<std::endl;
std::cout << (ascii2ulong("AB", 2) < ascii2ulong("B", 1))<<std::endl;
std::cout << (ascii2ulong("AB", 2) < ascii2ulong("A", 1))<<std::endl;
return 0;
}
但请注意:在做你正式也就侵犯了分配的地址范围,这样的方式(如果您的原始字符串具有<8个字节分配)。 如果你的内存完整性检查运行一个程序,它可能会产生一个运行时错误。 为了避免这种情况,你当然可以使用memcpy
复制的字节数,你在地方的需要uint64_t i = (*(uint64_t*)s);
:
uint64_t i;
memcpy(&i,s,std::min(len,8));
如果某些硬件加速用于memcpy
你的机器(这是有可能的),可能在效率方面是不坏。
文章来源: Short (ASCII, 7-bit per character) string storage and comparison optimization in C++