这个按位表达的逻辑更好?

时间:2012-01-04 04:19:36

标签: c# c++ logic bit-manipulation bitwise-operators

我正在处理一个处理使用哈希值的文件的程序。数据分为块长度0x1000。我需要计算具有特定起始和结束偏移的段的块数量。

例如,如果段的起始偏移量为0x2000且结尾为0x3523,则意味着它占用两个块,0x2000和0x3000。它不占用数据块中的完整0x2000字节,但当它在其中时它被认为是“占用块”。我的第一个想法是:

( ( EndingOffset - StartingOffset ) + 0xFFF ) >> 0xC

这相当于Math.Ceil((EndingOffset - StartingOffset) / 0x1000),但我是按位运算符的新手,并且喜欢使用它们的挑战。

无论如何,逻辑是有缺陷的,因为,如果起始偏移是0x3D8A和结束偏移0x671D,这就是我的情况,两者之间的差异是0x2993。向上舍入为0x3000或三个块。该段实际上占用了四个,0x3000,0x4000,0x5000和0x6000。所以我的下一班火车,不幸的是我的最后一班,是找到该段所在的第一个块的偏移量与该段不在的第一个块的偏移量之间的差异。

使用0x3D8A和0x671D,这将我带到(0x7000 - 0x3000) >> 0xC,它成功地产生了正确数量的块,4。我写它的方式是我想要改进的,即:

BlockSize = ((((OffsetEnd + 0xFFF) >> 12) + 1) - ((OffsetStart + 0xFFF) >> 12));

我知道我已经过度复杂化了一个简单的问题,但是我无法将我的小脑袋包裹起来如何更好地编写它。

编辑:那令人尴尬。我不知道我是怎么来的而不是

(((OffsetEnd + 0xFFF) >> 12) - (OffsetStart >> 12));

虽然似乎还不完整。

编辑2:对不起,忘了提到结束偏移是独占的,不包括在内,并且是段的最后一个字节之后的位置意思是:

(((OffsetEnd - 1 + 0xFFF) >> 12) - (OffsetStart >> 12));

编辑3:离开Kerek的回答,我最终得到了:

BlockSize = 1 + (offsetEnd - 1 >> 12) - (offsetStart >> 12);

..或者,从0开始计算,

BlockSize = (offsetEnd - 1 >> 12) - (offsetStart >> 12);

编辑4:忘记从零开始计数,我坚持:

BlockSize = 1 + (offsetEnd - 1 >> 12) - (offsetStart >> 12);

2 个答案:

答案 0 :(得分:0)

假设您的数据范围为[start, end),则非常简单:

unsigned int start_block = start_offset / 0x1000;
unsigned int end_block = end_offset / 0x1000;

unsigned int number_of_blocks = end_block - start_block + (end_offset > start_offset && end_offset % 0x1000 > 0 ? 1 : 0);

我想,/ 0x1000的相当于>> 12是{{1}}。

您的数据将占用块范围[start_block,end_block)。注意,块0是[0x0000,0x1000),块1是[0x1000,0x2000)`等等。

正如@Ron指出的那样,你需要一个条件来区分最后一个(“一个过去”)块是否为空,并在后一种情况下将块计数增加一个。

答案 1 :(得分:0)

((EndingOffset - StartingOffset)+ 0xFFF)>> 0xC +(StartingOffset&〜(0xFFF)!= 0)

这将有你简洁的开头,它将看看StartingOffset是否落在块边界上。如果没有,请添加1.