比较字符是否相等而不进行分支
compare chars for equality without branching
关于之前我想优化这个函数的问题:
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]) & 0x80) >> 7
代替s1i == s2[j] ? 0 : 1
来防止条件跳转。这个技巧是错误的,用户删除了他的评论,但我想知道是否真的有办法做到这一点。
假设代码
s1i == s2[j] ? 0 : 1
确实为您提供了一个分支操作,这是您想要避免的,您可以简单地尝试以下操作:
!(s1i == s2[j])
应该会产生相同的效果,并且可以帮助编译器删除分支。或者,您可以反向逻辑并写入
s1i != s2[j]
对于这种类型的优化,始终不能保证这将实际达到您希望的结果。优化器做了很多聪明的事情,试图预测它们对你的技巧的反应通常是非常困难的。因此,即使在最好的情况下,您所能做的就是尝试不同的解决方案并比较得到的二进制代码。
为什么不使用!(s1i == s2[j])
或(s1i != s2[j])
,因为bool到int的转换是隐式的
不是一个实用的答案,而是解决一个难题。
创建一个数组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]
为1
相关文章:
- C++字符*缓冲区的大小
- HEX值到wchar_t字符(UTF-8)的转换
- 为什么 Serial.println(<char[]>);返回随机字符?
- 我的字符计数代码计算错误.为什么
- 字符串-C++后显示的随机字符
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 如何在C++中从字符串中分割字符
- 为什么msgrcv()将垃圾字符馈送到缓冲区
- 指向指向字符数组的指针数组的指针
- IPC使用多个管道和分支进程来运行Python程序
- 如何用转义符替换字符串中的所有特殊字符
- 为什么 sscanf 无法从一个字符串中读取uint64_t和字符?
- 比较字符数组
- 将字符指针十六进制转换为字符串并保存在文本文件C++中
- 从矢量<无符号字符>转换为字符* 包括垃圾数据
- 如何使用Crypto++并为RSA返回可打印的字节/字符数组
- 如何在C++中确定文本文件中的元素是字符还是数字
- 如何将一个ostringstream十六进制字符串字符对转换为单个unit8t等价的二进制值
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- 比较字符是否相等而不进行分支