C++线性概率计数器

 

      线性概率计数器,用于基数估计。所谓基数,就是数据中不重复的数据有多少个。例如共有N个数据,开辟一片长度为M的bitmap,清零,对N个数据进行遍历,每个数据

取哈希,再对M取模,得到的值为i,于是将bitmap中第i个元素置位为1,最后统计bitmap中0的比例rate,计算-M*ln(rate)的值,即为N个数据中基数的估计值。

 

#include <stdio.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>

#define  BIG 100000  // BIG个整数
#define  SM  2000      // SM个unsigned char,作为bitmap
typedef unsigned int uint;
typedef unsigned char uchar;


uint ai[BIG];   // 计算的数据

uchar uclist[SM]; // 1000*8  //bitmap

void SetBit(uchar *p, uint n)  // 对bitmap p的第n个位置1
{
	uint n1=n/8;
	uint n2=n%8;
	p[n1] = p[n1] | (1<<n2);
}

uint hash( uint a)   // 整数哈希函数,别的地方抄来的。用好的哈希函数很重要,效果比直接取模好的多
{ 
	a = (a+0x7ed55d16) + (a<<12); 
	a = (a^0xc761c23c) ^ (a>>19); 
	a = (a+0x165667b1) + (a<<5); 
	a = (a+0xd3a2646c) ^ (a<<9); 
	a = (a+0xfd7046c5) + (a<<3); // <<和 +的组合是可逆的 
	a = (a^0xb55a4f09) ^ (a>>16);  
	return a; 
}

uint GetBit(uchar *p, uint n)  // 取得bitmap第n个位的值
{
	uint n1=n/8;
	uint n2=n%8;
	uchar ta=p[n1];
	ta = (ta>>n2)&0x01;
	return ta;
}

uint count(uint *ip, uint ni, uchar *cp, uint nc) // nc为数组大小,概率计数器,返回的是bitmap中1的个数
{
	uint i;
	for (i=0; i<ni; i++)
	{
		SetBit(cp, (hash(ip[i]))%(nc*8));
	}
	uint s=0;
	for (i=0; i<nc*8; i++)
	{
		s += GetBit(cp,i);
	}
	return s;


}
// 测试
int main()
{

	srand((uint)time(NULL));  //随机数种子
	uint i;
	for (i=0; i<BIG; i++)
	{
		ai[i]=3*i;	
	}

	for (i=0; i<SM; i++)
	{
		uclist[i]=0;
	}
	uint s = count(ai, BIG, uclist, SM);

	double f = double(SM*8-s)/double(SM*8);
	f = -8.0*SM*log( f);
	printf("bitmap size: %d\n bitmap 1 的数量: %d\n估计基数: %f \n实际基数:%d\n (错误率:%f)\n", 8*SM, s, f, BIG,abs(f-BIG)/BIG);
	

	return 0;
}


运行截图:

SM=2000

SM=4000

SM=6000

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值