Я работаю над программой, которая работает с файлом, использующим хэши. Данные разбиты на блоки длиной 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));
edit 3: Отходя от ответа Керека, я получаю:
BlockSize = 1 + (offsetEnd - 1 >> 12) - (offsetStart >> 12);
..или, считая от 0,
BlockSize = (offsetEnd - 1 >> 12) - (offsetStart >> 12);
редактировать 4: Забудьте о счете с нуля, я придерживаюсь:
BlockSize = 1 + (offsetEnd - 1 >> 12) - (offsetStart >> 12);