汉明距离(hamming distance ) 的代码实现

  1.  简介  详见维基百科

概念:

信息论中,两个等长字符串之间的汉明距离是两个字符串对应位置的不同字符的个数。换句话说,它就是将一个字符串变换成另外一个字符串所需要替换的字符个数。例如:

10111011001001之间的汉明距离是2。

21438962233796之间的汉明距离是3。

"toned"与"roses"之间的汉明距离是3。

汉明重量是字符串相对于同样长度的零字符串的汉明距离,也就是说,它是字符串中非零的元素个数:对于二进制字符串来说,就是1的个数,所以11101的汉明重量是4。

特性:

对于固定的长度n,汉明距离是该长度字符向量空间上的度量,很显然它满足非负、唯一及对称性,并且可以很容易地通过完全归纳法证明它满足三角不等式

两个字ab之间的汉明距离也可以看作是特定运算−的ab的汉明重量。

对于二进制字符串ab来说,它等于a 异或b以后所得二进制字符串中“1”的个数。另外二进制字符串的汉明距离也等于n超正方体两个顶点之间的曼哈顿距离,其中n是两个字串的长度。

   2.  实现:

/*
 *  =>实现自己的hamming distance计算代码
 *  =>面向图像特征描述子的计算要求
 *    1. feature长度128,256,..千万
 *    2. 实现在海量数据中快速匹配(笨的暴力匹配)
 */


#include <stdio.h>
#include <stdlib.h>

// 使用SSE
#include <nmmintrin.h>  

#define USE_SSE4 1

//定义特征描述子的长度,
#define FEATURE_LENGTH  128

typedef unsigned long long  uint64;
typedef unsigned int        uint32;



//c 实现的简单的hamming distance 计算,原理
int hamming_dis(unsigned x, unsigned y)
{
	int dist;
	unsigned val;

	dist = 0;
	val = x ^ y;  // X OR Y hammming Dis 是异或计算的值中“1”的个数
	
	while(val != 0) //统计val的二进制表示中“1”的个数
	{
	     dist++;
		 val &= val - 1;
	}
	return dist;
}
 
//https://tekpool.wordpress.com/2006/09/25/bit-count-parallel-counting-mit-hakmem/
//实现二进制数据并行统计
int BitCount(unsigned int u)
 {
         unsigned int uCount;

         uCount = u
                  - ((u >> 1) & 033333333333)
                  - ((u >> 2) & 011111111111);
         return
           ((uCount + (uCount >> 3))
            & 030707070707) % 63;
 }

// 计算uint64 长度的hamming distance
uint64 _m_hamming_distance_uint64(uint64 x, uint64 y)
{
    uint64 dist;
	uint64 val;

	dist = 0;
	val  =  x ^ y;

	while(val != 0)
	{
	    dist++;
		val &= val - 1;
	}
	return dist;
}



//计算空间长度更长的hamming distance,
int _m_hamming_dis(const unsigned char* x, const unsigned char *y)
{
#ifdef USE_SSE4
	uint64 dist;

	uint64  *xx = (uint64 *)x;
	uint64  *yy = (uint64 *)y;
	dist = 0;
	
	//此处可以尝试添加并行处理!
	for(unsigned i = 0; i <FEATURE_LENGTH /( sizeof(uint64) * 8 ); ++i)
	{
		//dist += _m_hamming_distance_uint64(xx[i],yy[i]);
		//printf("xx, yy, dist = %d, %d, %d\n",dist,xx[i],yy[i]);
		dist += _mm_popcnt_u64(xx[i] ^ yy[i]);
	}
	return (int)dist;
#else
	int dist;

	uint64  *xx = (uint64 *)x;
	uint64  *yy = (uint64 *)y;
	dist = 0;
	
	//此处可以尝试添加并行处理!
	for(unsigned i = 0; i <FEATURE_LENGTH /( sizeof(uint64) * 8 ); ++i)
	{
		//dist += _m_hamming_distance_uint64(xx[i],yy[i]);
		// 或者
		dist += BigCount(xx[i] ^ yy[i])
	}
	return dist;
#endif
}



// 测试函数
int main()
{

	//printf("ham_dis = %d",hamming_dis(4,8));
	
	unsigned  *a = (unsigned *)malloc(256); //256  bit
	unsigned  *b = (unsigned *)malloc(256); //256

	for(unsigned i = 0; i < 256 /(sizeof(unsigned)*8); ++i)
	{
	    a[i] = i + 1;
		b[i] = i + 2;
		printf("a,b = %d,%d\n",a[i],b[i]);
	}

	uint64 *aa = (uint64 *)a;
	uint64 *bb = (uint64 *)b;

	for(unsigned i = 0; i < 256/(sizeof(uint64)*8); ++i)
	{
	    printf("aa,bb = %d, %d\n",aa[i],bb[i]);
	}


	//测试计算长数据hamming dis结果正确
	printf("ham_dis = %d\n",_m_hamming_dis((const unsigned char *)a,(const unsigned char *)b));
	
	system("pause");
	return 0;
}


转载于:https://my.oschina.net/badboy2/blog/381676

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值