bitmap

阅读 / 问答 / 标签

BitMap原理与实现

比较经典的问题是: 在只能够使用2G的内存中,如何完成以下操作: ①:对10亿个不重复的整数进行排序。 ②:找出10亿个数字中重复的数字。 无论是排序还是找重复的数字都需要将这10亿个数字加入到内存中在去进行操作,很明显,题目给出的2G内存限制说明了在这样的场景下是不能够将所有数都加入到内存中的 1000000000* 4/(1024* 1024* 1024) = 3.725G 那么这时候就需要用到 BitMap结构了 bitMap使用一个bit为0/1作为map的value来标记一个数字是否存在,而map的key值正是这个数字本身。 相比于一般的数据结构需要用4个byte去存储数值本身,相当于是节省了 4*8:1 = 32倍的内存空间 bitMap不一定要用bit数组,可以使用 int,long等等的基本数据类型实现,因为其实质都是在bit位上存数据,用哪种类型只是决定了最终实现出来的BitMap的内置数组中单个元素存放数据的多少 u2003u2003u2003u2003例如:java中的BitSet使用Long数组 BitMap的实现当然少不了位运算,先来明确几个常见位运算,这是实现BitMap的基础: set(bitIndex): 添加操作 u2003u2003u2003u20031 .确定该数处于数组中的哪个元素的位上 u2003u2003u2003u2003 int wordIndex = bitIndex >> 5; 因为我用的是int[]实现,所以这里右移 5 位(2^5 = 32) u2003u2003u2003u20032 .确定相对于该元素中的位置偏移 u2003u2003u2003u2003 int bitPosition = bitIndex & ((1 << 5) - 1); 这里相当于是 bitIndex % (1<<5)的取模运算,因为当取模运算的除数是2的次幂,所以可以使用以下的位运算来计算,提升效率(对比HashMap的容量为什么总是2的幂次方的问题,HashMap求下标时也是使用 hash&(n-1)) tips: 位运算的优先级是低于+,-等等的,所以要加上括号,防止发生不可描述的错误 u2003u2003u2003u20033 .将该位置1 u2003u2003u2003u2003 bits[wordIndex] |= 1 << bitPosition; 相当于是将指定位置处的bit值置1,其他位置保持不变,也就是将以这个bitIndex为key的位置为1 tips: 这里是参考了网上的各位大佬的文章,取余 + 按位或,又对比了下BitSet的源码: u2003u2003u2003u2003 words[wordIndex] |= (1L << bitIndex); 没有取余操作,直接|,这两个一样吗?答案当然是一样的 举个栗子: u2003u2003u2003u2003 1 << 148 == 1<< 20 u2003u2003u2003u2003 u2003u2003u2003u2003 1L << 125 ==1L<< 61 即对于int和long型数据,直接左移其位数相当于是附带了对其的取模操作 总结 :使用Bit-map的思想,我们可以将存储空间进行压缩,而且可以对数字进行快速排序、去重和查询的操作。 Bloom Fliter是Bit-map思想的一种扩展,它可以在允许低错误率的场景下,大大地进行空间压缩,是一种拿错误率换取空间的数据结构 当一个元素加入布隆过滤器中的时候,会进行哪些操作: 当我们需要判断一个元素是否存在于布隆过滤器的时候,会进行哪些操作: 然后,一定会出现这样一种情况: 不同的字符串可能哈希出来的位置相同 (可以适当增加位数组大小或者调整我们的哈希函数来降低概率),因此: 布隆过滤器可能会存在误判的情况 总结来说就是: 布隆过滤器说某个元素存在,小概率会误判。布隆过滤器说某个元素不在,那么这个元素一定不在 。 Bloom Filter的应用: 常用于解决缓存穿透等场景。

喷绘机打印tiff bitmap与true type font哪个最好

TrueTypeFont是一种字库名称。字库是输出设备的一个组成部分。由于汉字不同干西方字体,字符集非常庞大,不能用单字节表示,因此postscriptleveli的rip不能使用汉字,很多西文软件也不支持汉字。桌面出版系统使用的字库有两种标准:postscript字库和truetype字库。这两种字体标准都是采用曲线方式描述字体轮廓,因此都可以输出很高质量的字形。postscript汉字库分为显示字库和打印字库,显示字库安装在制作计算机上,用来制作版面时显示用,通常由低分辨率的点阵字构成。打印字库要挂接在rip上,在解释页面时由rip把需要的字库调人页面并解释成记录的点阵。postscript汉字使用方便,输出速度快,是输出中心必备的。另一种常用的字库标准是truetype字库,truetype字体是windows操作系统使用的唯一字体标准,macintosh计算机也用truetype字体作为系统字体。truetype字体的最大优点是可以很方便地把字体轮廓转换成曲线,可以对曲线进行填充,制成各种颜色和效果,它可以进一步变形,制作特殊效果字体,因此经常用来制作一些标题字或花样字。truetype字便宜,字款丰富。但一般情况厂truetype字不能直接由rip输出。需要经过特殊处理,比如转成曲线或输出时下载,使用起来较麻烦。速度也要慢一些,尤其是处理大量文字时很不方便,因此不适合用来作为页面的正文文字使用。truetype字体也用来作为postscript字库的显示字用,各字库公司同时都有这两种标准的产品。因此当使用truetype字体制作版面时,输出时仍然可以将它代换成postscript字库输出

C# 使用bitmap绘图,base.Invalidate()重画,有残影怎么办

这个要用到缓冲区的技术,就是你要定义一个缓冲区,然后图是画在缓冲区上的,画完之后,再把缓冲区的图绘制到你的当前工作区。

电脑开机时检测到correcting errors in the volume bitmap就卡了

未知的硬盘错误

笔记本出现correcting errors in the volume bitmap 我应该怎么处理 是硬盘坏了吗

硬盘错误。重装系统把

correcting errors in the volume bitmap怎么回事

未知的硬盘错误

电脑最后提示correcting errors in the volume bitmap需要怎么做才能弄好

1、correcting errors in the volume bitmap-----是在对卷位图中的误差进行校正中,这是个比较麻烦的硬盘错误。2、建议开机按DEL键(笔记本按F2键)进BIOS设置光盘或U盘引导电脑进WinPE(需要你有带WinPE的光盘或U盘启动盘,没有就买或自己做一个)。3、进PE后使用DiskGenius>检测和修复硬盘坏道,然后重新格式化硬盘,重装系统吧。

C++ 怎样把一个BITMAP中的数据读到一个数组里?

unsigned char* m_pdib; BITMAPINFOHEADER* m_pBIH;m_pBIH=(BITMAPINFOHEADER*)m_pdib;m_pBIH->biSize m_pBIH->biHeight m_pBIH->biWidth m_pBIH->biPlanes m_pBIH->biBitCount m_pBIH->biSizeImageu2026u2026

数据结构与算法 - Bit-Map , RoaringBitmap

BitMap(位图)就是用一个bit位来标记某个元素所对应的value,而key即是该元素,由于BitMap使用了bit位来存储数据,因此可以大大节省存储空间。BitMap解决 海量数据寻找重复、判断个别元素是否在海量数据当中 等问题 假设我们要对0-7内的5个元素(4,7,2,5,3)进行排序(这里假设元素没有重复)。我们可以使用BitMap算法达到排序目的。要表示8个数,我们需要8个byte。 1. 首先我们开辟一个字节(8bit)的空间,将这些空间的所有的bit位都设置为0 2. 然后遍历这5个元素,第一个元素是4,因为下边从0开始,因此我们把第五个字节的值设置为1 3. 然后再处理剩下的四个元素,最终一个字节的状态如下图 4. 现在我们遍历一次byte区域,把值为1的bit的位置输出(2,3,4,5,7),这样便达到了排序的目的 从上面的例子我们可以看出,BitMap算法的思想还是比较简单的,关键的问题是如何确定10进制的数到2进制的映射图 假设需要排序或则查找的数的总数N=100000000,BitMap中1bit代表一个数字,1个int = 4Bytes = 4*8bit = 32 bit,那么N个数需要N/32 int空间。所以我们需要申请内存空间的大小为int a[1 + N/32],其中:a[0]在内存中占32为可以对应十进制数0-31,依次类推: a[0]-----------------------------> 0-31 a[1]------------------------------> 32-63 a[2]-------------------------------> 64-95 a[3]--------------------------------> 96-127 a[n]--------------------------------> n 32 - n 32+31 那么十进制数如何转换为对应的bit位,下面介绍用位移将十进制数转换为对应的bit位: 1. 求十进制数在对应数组a中的下标 十进制数0-31,对应在数组a[0]中,32-63对应在数组a[1]中,64-95对应在数组a[2]中………,使用数学归纳分析得出结论:对于一个十进制数n,其在数组a中的下标为:a[n/32] 2. 求出十进制数在对应数a[i]中的下标 例如十进制数1在a[0]的下标为1,十进制数31在a[0]中下标为31,十进制数32在a[1]中下标为0。 在十进制0-31就对应0-31,而32-63则对应也是0-31,即给定一个数n可以通过模32求得在对应数组a[i]中的下标。 3. 位移 对于一个十进制数n,对应在数组a[n/32][n%32]中,但数组a毕竟不是一个二维数组,我们通过移位操作实现置1 a[n/32] |= 1 << n % 32 移位操作:a[n>>5] |= 1 << (n & 0x1F) n & 0x1F 保留n的后五位 相当于 n % 32 求十进制数在数组a[i]中的下标 bitmap 适用于数据较为密集的时候,但是对于稀疏数据的话, bitmap 存在存储空间的浪费, 举个例子:若只存放0~40亿中的第40亿的数据,此时前面的存储空间白白浪费了 为了解决位图在稀疏数据下的问题,目前有多种压缩方案以减少内存提高效率:WAH、EWAH、CONCISE、RoaringBitmap等。前三种采用行程长度编码(Run-length-encoding)进行压缩,RoaringBitmap则是在压缩上更进一步,并且兼顾了性能 roaringbitmap 简称RBM,属于是bitmap的一个进化,即压缩位图,不过在roaringbitmap中不只包含bitmap这一种数据结构,而是包涵了多种存储的方式,以此来达到压缩位图的目的 在roaringbitmap中共有4种Container: arraycontainer(数组容器),bitmapcontainer(位图容器),runcontainer(行程步长容器),sharedcontainer(共享容器) 参考:

怎么将一张普通的png图片转换层bitmap

需要通过制图软件来转换,如PHOTOSHOP,PHOTOIMPACT等

android bundle能传递bitmap吗

传id呗,

android开发创建的Bitmap和屏幕不一样

Bitmap.createBitmap(metrics.widthPixels,metrics.heightPixels, Bitmap.Config.ARGB_8888);ImageView宽高都是match_parent上面一个toolbar,下面就是图创建后图只有上边是正常的,左右两边都没有到屏幕的边,屏幕边缘动作能监控到图里;下面图能到屏幕的下面,但是下面有一大行空白画不到。看一下布局给的多少,imagview必须给wrap partent属性。

Clickhouse的bitmap函数

从无符号整型(UInt8、UInt32、UInt64等)array构造bitmap 将bitmap转成整型array 返回bitmap中,range_start到range_end区间内(不包含renge_end)的子集bitmap对象 返回bitmap中,从range_start开始的cardinality_limit个元素组成的子集bitmap对象 判断指定bitmap中是否存在e元素 bitmap1中是否包含bitmap2中的元素,只要有一个相同的元素,就返回1,否则返回0. bitmap1中是否全部包含bitmap2中的元素,全部包含就返回1,否则返回0. 返回bitmap的基数 将bitmap中的元素进行转换,将存在于from_array的元素,一次转换成to_array的对应元素。 上面的例子中,依次将bitmap中,5转成2,999(不存在)转成888,2转成20。因为就bitmap中不存在999,所以新bitmap没有888;因为将5转成2,又将2转成20,所以新bitmap中去掉了5和2元素,新加了20元素 求两个bitmap的交集 求两个bitmap的并集 求两个bitmap的异或 求bitmap1与bitmap2的与非

BitMap及其在ClickHouse中的应用

问题要从面试或者大数据场景下最常见的一个算法说起,问题是这样的,假如有几十亿个unsigned int类型的数据,要求去重或者计算总共有多少不重复的数据?最简单的办法就是直接利用一个HashMap,进行去重。但是这里面有个内存使用量的问题,几十亿个元素,即使不考虑HashMap本身实现所用到的数据结果,单单key本身,假如每个unsigned int占用4个字节,简单算一下的话,这里都需要几十GB的内存占用,因此,这里就引出了BItMap。 BItMap的思想非常简单,就是用一个bit表示一个二元的状态,比如有或者没有,存在或者不存在,用bit本身的位置信息,对应不同的数据。比如针对上面的问题,我们可以开辟一个2^32 bit的内存空间,每一个bit存储一个unsigned int类型的数据,有就是1,没有就是0,总共需要存储unsigned int类型的最大范围个数据,也就是2^32 个数据,这个2^32其实就是所谓的基数。如下图所示: 假如存在数字8,那就把对应的第8位的值赋为1。上图插入的数据为1、3、7、8。接着依次把所有的数据遍历然后更新这个BitMap。这样我们就可以得到最终结果。 假如上面的问题变成了对几十亿个URL做判断,那应该怎么去做呢?URL没有办法和BitMap的位置关系对应上,所以,我们需要加一层哈希,把每个URL经过哈希运算得到一个整数,然后对应上BitMap。如下图所示: 但是有哈希,肯定会存在碰撞,如果BitMap基数(也就是长度)比较小,那碰撞的概率就大,如果基数比较大,那占用的空间又会比较多。Bloom Filter的思想就是引入多个哈希函数来解决冲突的问题。也就是说对每个URL,经过多个哈希函数的运算,得到多个值,每个数值对应的BitMap的对应的位置都赋值为1。这个两个URL经过多个哈希函数结果还是一样的概率就大大降低。 但是由于依然存在冲突的可能性(其实冲突就是来源于我们BitMap的长度小于了数据量的基数,这也就是牺牲了准确性换来了空间使用的减少),所以Bloom Filter 存在假阳性的概率,不适用于任何要求 100% 准确率的场景,也就是说Bloom Filter 只能用来判无,不能用来判有。比如一个URL经过多次哈希运算之后,发现对应的BitMap的位置都已经是1了,那也不能说明,这个URL之前存在过了,也有可能是哈希冲突的结果。但是一个URL经过多次哈希运算之后,发现对应的BitMap的位置不是都是1,那当前URL之前一定是没有存在过的。 可以看到,Bloom Filter 引入多次哈希,在查询效率和插入效率不变的情况下,用较少空间的BitMap解决大数据量的判断问题。 大部分情况下仅仅做有无的判断是不能满足使用需求的,我们还是需要真正意义上的BitMap(可以方便的用来做交并等计算),但是最好可以在基数比较大的时候,依然可以占用相对比较小的空间。这就是RoaringBitMap所要实现的。 简单来说RoaringBitMap是BitMap的一种带索引的复杂BitMap数据结构。以32位的RoaringBitMap为例,首先划分2^16 个空间(Container),每个Container内部都是一个大小为2^16 bit的BitMap,总的内存使用量还是2^32 = 512Mb。这样的话和普通的BitMap是没有区别的,而RoaringBitMap的创新之处在于每个Container内的BitMap是在没有使用到的情况下是可以不分配内存空间的。这样可以大大减小内存的使用量。 (这个图片是Roaring Bitmaps: Implementation of an Optimized Software Library 论文原图) 要将一个4个字节的数据插入RoaringBitMap,首先要用数据的高16位,找到对应的Container,然后用数据的低16在Container中插入。 在每个Container内部,RoaringBitMap不是简单的用BitMap来进行数据的存储,而是把Container的类型划分为几种,不同的Container用来存储不同情况的数据。 当2个字节(4个字节的原数据,低16位用来插入具体的Container中)的数据,总的个数小于4096个的时候,当前Container使用 array Container。为什么是4096个呢?4096*2B=8Kb,而一个Container如果是bitmap的结构的话,最多也就是2^16bit=8Kb的空间。所以这里当数据个数小于4096使用array Container会更节省空间。当然这里名字为array Container,实际上是链表结构,不需要最开始就初始化4096个short int的数组。 当array Container存储的数到4096个的时候(也就是使用内存到8Kb的时候),array Container会转换为bitmap container,bitmap container就是一个2^16 bit普通的bitmap,可以存储2^16 = 65536个数据。这个8Kb还有一个好处,是可以放到L1 Cache中,加快计算。 这个严格的说,只是一种数据压缩存储方法的实现。其压缩原理是对于连续的数字只记录初始数字以及连续的长度,比如有一串数字 12,13,14,15,16 那么经过压缩后便只剩下12,5。从压缩原理我们也可以看出,这种算法对于数据的紧凑程度非常敏感,连续程度越高压缩率也越高。当然也可以实现其他的压缩方法。 RoaringBitMap其核心就在于加了一层索引,利用复杂的数据结构换取了空间上的效率。需要注意的是这里并没有增加计算的复杂度,其出色的数据结构让其在做交并计算的时候性能也毫不逊色。 ClickHouse中有bloom_filter类型的Skipping indexs,可以方便的用来过滤数据。 ClickHouse实现了大量的BitMap的函数,用来操作BitMap。ClickHouse中的BitMap在32位的时候用的是Set实现的,大于32位的时候也是使用RoaringBitMap实现的。我们这里不看具体的函数,我们来看一个典型的使用场景。 最常见的一个场景是根据标签来进行用户的圈选。常见的解决办法是有一张用户标签表,比如 要查询标签tag1="xx"和tag2="xx"的用户需要执行SQL: 但是由于不可能对每个tag列构建一级索引,所以这条SQL执行的效率并不高。可选的一种方式是先构建关于标签的BitMap数据结果,然后进行查询: (1) 创建tag的bitmap表: (2)写入数据 (3)查询 如果有多张tag表,进行交并计算(要比普通的用户表进行JOIN或者IN计算要高效很多):

c#:bitmap类型怎么转换成intptr呢

.GetHbitmap()