在我想要优化此功能的previous question上:
static
lvh_distance levenshtein_distance( const std::string & s1, const std::string & s2 )
{
const size_t len1 = s1.size(), len2 = s2.size();
std::vector<unsigned int> col( len2+1 ), prevCol( len2+1 );
const size_t prevColSize = prevCol.size();
for( unsigned int i = 0; i < prevColSize; i++ )
prevCol[i] = i;
for( unsigned int i = 0, j; i < len1; ++i )
{
col[0] = i+1;
const char s1i = s1[i];
for( j = 0; j < len2; ++j )
{
const auto minPrev = 1 + std::min( col[j], prevCol[1 + j] );
col[j+1] = std::min( minPrev, prevCol[j] + ( s1i == s2[j] ? 0 : 1 ) );
}
col.swap( prevCol );
}
return prevCol[len2];
}
用户评论说我可以用s1i == s2[j] ? 0 : 1
替换((s1i - s2[j]) & 0x80) >> 7
以防止条件跳转。诀窍是错误的,用户删除了他的评论,但我想知道是否真的有办法做到这一点。
答案 0 :(得分:3)
假设代码
s1i == s2[j] ? 0 : 1
确实为您提供了分支操作,您真的想要避免,您只需尝试以下操作:
!(s1i == s2[j])
这应该会产生相同的效果,并可能有助于编译器删除分支。或者,您可以反转逻辑并编写
s1i != s2[j]
与这种类型的优化一样,永远不能保证这将实际达到您希望的结果。优化器可以做很多聪明的事情,并且试图预测它们对你的技巧的反应往往很困难。因此,即使在最好的情况下,您所能做的就是尝试不同的解决方案并比较生成的二进制代码。
答案 1 :(得分:2)
为什么不使用以下内容:!(s1i == s2[j])
或(s1i != s2[j])
因为bool到int转换是隐式的
答案 2 :(得分:1)
不是一个实际的答案,而是解决一个难题
创建一个数组one_or_zero[UCHAR_MAX+1]
,用1填充,one_or_zero[0] = 0;
现在你可以做prevCol[j] + one_or_zero[s1i^s2[j]])
之类的事情了
这将导致s1i==s2[j]
上的0,否则将添加到prevCol[j]