c# - 这个按位表达式有更好的逻辑吗?

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

我正在开发一个程序来处理使用散列的文件。数据被分成长度为 0x1000 的 block 。我需要计算具有特定起始和结束偏移覆盖的段的 block 数量。

例如,如果段的起始偏移量为 0x2000,结束位置为 0x3523,则表示它占用了两个 block ,0x2000 和 0x3000。它不占用数据 block 中的完整 0x2000 字节,但当它在其中时被认为是“占用一个 block ”。我的第一个想法是:

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

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

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

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

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

我知道我已经把一个简单的问题复杂化了,但是我的小脑袋想不出如何把它写得更好。

编辑:这很尴尬。我不知道我是怎么想到的而不是

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

虽然看起来还不完整。

edit 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);

最佳答案

假设您的数据范围为 [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 的 bitfiddling 等价物是 >> 12

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

正如@Ron 指出的那样,您需要一个条件来区分最后一个(“one-past”) block 是否为空,并在后一种情况下将 block 计数递增 1。

关于c# - 这个按位表达式有更好的逻辑吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8721963/

相关文章:

c# - 如何使用 WebBrowser 控件以编程方式更改打印机设置?

c# - for循环背后的逻辑

c# - Observable.Window 和 .Zip 无法正常运行

c++ - 我如何克服这个 C++ vector 排序错误?

c++ - 如何使用大 vector 初始化来避免 "compiler limit: compiler stack overflow"?

c++ - 如何返回带参数的 lambda 函数?

mysql - 从表 A 中获取不在表 B 中的记录

css - 如何在CSS中建立父节点-->节点关系?

c# - 为 Epplus Excel 文件创建最小起订量

c# - byte = byte - byte 需要类型转换吗?