Каков наилучший способ сделать java-кодирование для таких операций на уровне байтов?

Я читаю о некоторых проблемах, связанных с подходами к оптимизации.
В задаче о том, как сортировать числа в определенном диапазоне, решением является использование растрового изображения. И если число может появиться, например. до 10 раз используйте полубайты для отображения чисел и в качестве счетчиков для представления количества вхождений.
Концепция, которую я хорошо понимаю. Моя проблема заключается в том, как реализовать это на Java простым способом.

Я застрял на битовых операциях.
Например, для первой части увеличения счетчика на 1 я мог подумать о следующем:

Найдите байт
Например. bitValue[i]
Затем выполните byte tmp = bitValue[i] & 0x0F, чтобы получить младшие биты (если счетчик является младшим счетчиком).
Затем выполните tmp = tmp + 1, чтобы увеличить значение на 1.
Затем выполните bitValue[i] >> 2, чтобы очистить младшие биты, и затем bitValue[i] <<2, чтобы восстановить. Теперь у нас те же старшие биты, что и в оригинале, а младшие биты очищены.
Затем выполните bitValue[i] |= tmp, чтобы установить младшие биты.
Теперь bitValue счетчик младших битов увеличен на 1. Правильно?

Для старшего бита это будет тот же процесс, но для старших битов.

Затем, когда я должен проверить, что такое номер счетчика.

Я решил использовать битовые маски:
0x0 0x1 0x2 и т. д. и использовать OR для проверки текущего номера счетчика.

Все это кажется слишком сложным. Я на правильном пути? Как эти операции лучше всего решаются в Java-кодировании?

Любой вклад, руководство по этому вопросу приветствуется.


person Cratylus    schedule 02.04.2012    source источник
comment
Вы изучаете оптимизацию или оптимизируете? Если вы на самом деле занимаетесь оптимизацией, определили ли вы проблему с производительностью или считаете, что то, что вы делаете, необходимо? FWIW, это, вероятно, не нужно.   -  person Dave    schedule 03.04.2012


Ответы (1)


Вы определенно на правильном пути. Вот некоторый конкретизированный код, который увеличивает первые четыре бита или вторые четыре бита int на заданную величину.

Обратите внимание, что здесь я использую int вместо byte. Даже если ваши данные относятся к категории byte, обычно гораздо проще работать с ними в формате int. Это связано с тем, что побитовые операторы Java, такие как |, & и <<, возвращают int. Так что проще всего работать с вашими данными как с int, а затем отбрасывать назад, как только вы сделали все свои биты.

Кроме того, если вам нужно иметь дело с большим блоком данных (возможно, больше, чем просто два счетчика, которые вы упомянули) на побитовом уровне, вы можете рассмотреть возможность взглянуть на BitSet.

public class Test {
    public static void main(String[] args)
    {
        int counter = 0;

        // increment the low bits by 3 and high bits by 2
        counter = addLowBits( counter, 3 );
        counter = addHighBits( counter, 2 );

        // print the hex string to verify
        System.out.println( Integer.toHexString( counter ) );
        System.out.println( "Low Counter: " + ( counter & 0x0F ) );
        System.out.println( "High Counter: " + ( ( counter & 0xF0 ) >> 4 ) );
    }

    public static int addLowBits( int counter, int increment )
    {
        // get the low bits
        int low = counter & 0x0F;

        // increment by 1
        low = low + increment;

        // mask the high bits and insert new low bits
        counter = (counter & 0xF0) | low;

        return counter;
    }

    public static int addHighBits( int counter, int increment )
    {
        // now get high bits
        int high = ( counter & 0xF0 ) >> 4;

        // increment by 1
        high = high + increment;

        // mask the low bits and insert new high bits
        counter = (counter & 0x0F) | ( high << 4 );

        return counter;
    }
}
person ulmangt    schedule 02.04.2012
comment
+1: Спасибо за ваш пример !!! Рад знать, что я не потерялся в этом. И для проверки того, что такое номер счетчика, идея состоит в том, чтобы проверить каждую битовую маску, например. 0x1 0x2 и т. д. один за другим, чтобы увидеть, какой из них установлен, чтобы узнать, какой номер находится в счетчике? - person Cratylus; 03.04.2012
comment
counter & 0x0F возвращает вам значение счетчика младших битов, а (counter & 0xF0) >> 4 — значение счетчика старших битов. Или это не те цифры, которые вы ищете? - person ulmangt; 03.04.2012
comment
Идея состоит в том, что если у меня есть 1 на входе, соответствующий счетчик будет увеличен на 1. Если 1 появится во входных данных 4 раза, тогда соответствующий счетчик будет иметь значение 4 (это то, что делает приращение, отслеживать вхождения). Позже, когда я захочу узнать, сколько 1 появилось на входе, я должен каким-то образом получить число 4 из счетчика. т.е. что 1 появилось 4 раз. Для этого я подумал AND с каждой битовой маской по одному. т.е. это 0x1? 0x2 в счетчике? 0x3 в счетчике? 0x4 в счетчике. Да, это 0x4. Это правильный метод? - person Cratylus; 03.04.2012
comment
Я не уверен, что циклически перебирает эти битовые маски, как вы предлагаете (если только я все еще не понимаю, чего вы пытаетесь достичь). Вам не нужно пробовать каждое двоичное значение по очереди. Вы можете просто взять значение счетчика (используя выражения из моего последнего комментария). Если нижний счетчик был увеличен четыре раза, то значение counter & 0x0F будет равно 0x4. - person ulmangt; 03.04.2012
comment
its easiest to work with your data as an int Разве это не ухудшает читаемость кода? кому-то, кто просматривает код, не ясно, что в моем примере меня действительно интересует bytes, а не ints. Или я неправильно думаю об этом? - person Cratylus; 03.04.2012
comment
Это правда. Хотя трудно судить о читабельности. Я думаю, что наличие кучи (byte) повсюду делает код уродливым и менее читаемым. Но это делает его более явным наверняка. Я бы сказал, попробуйте написать свой код обоими способами и посмотрите, какой из них вам больше нравится. - person ulmangt; 03.04.2012
comment
Я также должен упомянуть, что если вы заинтересованы в работе с большими порциями данных на побитовом уровне, BitSet может вас заинтересовать. - person ulmangt; 03.04.2012
comment
И последнее замечание. Я был обеспокоен тем, что, возможно, приращение на 1 было бы лучше, если бы я увеличивал с помощью побитовых операций. Правильно ли это? И как это можно было сделать? - person Cratylus; 03.04.2012
comment
Добавление примитивных типов (int/short/byte) происходит очень быстро. Если вы хотите добавить 1 к значению int, я не могу придумать ни одной причины не использовать оператор +. - person ulmangt; 03.04.2012