我遇到一个问题,即使用回溯来查找多个"单词"(它们不一定是真实的)有各种规则。一些规则涉及我可以拥有的元音数量。
我知道我可以使用开关,或带有元音数组的for循环,然后说所有不是元音的字母字符都是辅音,但由于这个函数可能会被称为几千次,我希望它尽可能快。
检查字符是元音还是辅音的最快方法是什么?
答案 0 :(得分:4)
最快的方法是创建一个bool
数组并使用字符值作为索引:
bool is_vowel[CHAR_MAX] = { false }; // initializes all values to false
void init() {
is_vowel['A'] = true;
is_vowel['a'] = true;
// etc.
}
现在,对于任何非负char
值ch
,is_vowel[ch]
如果是元音则为真,否则为假。
答案 1 :(得分:1)
如果您有ASCII字符,并且您知道该字符是一个字母(其ASCII代码大于或等于64),那么您可以这样做:
RecyclerView
如果您使用的是x86,那么您甚至可以删除bool isvowel(char v) {
return (0x208222>>(v&0x1f))&1;
}
部分(注意:根据标准,这是未定义的行为,但是&0x1f
编译下来到>>
,SHR/SAR
将自动屏蔽为0x1f:
v
注意:这是一个“脏”的解决方案,但是如果真的需要速度,有时脏解是最快的(基本上这个解决方案在魔术常量0x208222中存储32个元素表:为wovel设置位。 ,利用大小写字符具有相同的5个最低位)。
注意2:仅当表指针不在时,此版本才比表版本快。如果你做了很多检查,并且表指针已经在一个寄存器中,并且表在缓存中,则表版本更快。
答案 2 :(得分:1)
我没有其他想法。
这个答案只是为了提供其他人的基准。
bool undef_sarx_and(char v) {
return (0x208222>>v) // sarx %edi, %eax, %eax
&1; // andl $1, %eax
}
bool unsafe_one_load(char in) {
return bool_table[in]; // movsbq %dil, %rdi
} // movb table(%rdi), %al
bool safe_one_load(char in) {
auto index = static_cast<unsigned char>(in); // movzbl %dil, %edi
return bool_table[index]; // movb table(%rdi), %al
}
(iterate on data 1 MB for 800 times)
undef_sarx_and 209976800 2.71313 sec 309.185 MB/s
unsafe_one_load 209976800 2.4514 sec 342.197 MB/s
safe_one_load 209976800 2.18231 sec 384.391 MB/s
(iterate on data 100 MB for 8 times)
undef_sarx_and 209704768 3.76998 sec 222.511 MB/s
unsafe_one_load 209704768 3.72898 sec 224.957 MB/s
safe_one_load 209704768 3.72719 sec 225.065 MB/s
all with vectorization disabled (-fno-tree-vectorize)
我想没有什么可以击败@ pete-becker的表查找 但@ geza的hack非常引人注目,因为表查找分配了256个字节,而内在函数全部是免费的!