Упаковка двух шорт в один, работа с негативом и позитивом

Я создаю класс PackedUnsigned1616, который хранит два неподписанных шорта в одном int, и класс PackedSigned1616, в котором два подписанных шорта хранятся в одном int. Я читал о побитовых операциях, но я все еще не понимаю, как обращаться со знаками и без знака, а также со значениями, которые больше или меньше короткого диапазона (они передаются как два целых числа). Вот что у меня есть:

public final class PackedUnsigned1616 {
public final int field;

private static final int RIGHT = (2 << 15) - 1;
private static final int LEFT = ((2 << 31) - 1) ^ RIGHT;

public PackedUnsigned1616(int left, int right) {
    field = (left << 15) | (right & RIGHT);
}

public int getLeft() {
    return field >> 15;
}
public int getRight() {
    return field & RIGHT;
}

}

Вся эта концепция меня сильно смущает, поэтому, если бы вы могли пролить на нее немного света, это бы очень помогло.


person Caleb Jares    schedule 08.05.2011    source источник
comment
Ну, каково желаемое поведение? Самое большое короткое число, которое вы можете представить, это (2<<15)-1, поэтому, если вы вызовете конструктор с числом больше этого, что должно произойти?   -  person MatrixFrog    schedule 09.05.2011
comment
О, извините, я хочу, чтобы его зажали   -  person Caleb Jares    schedule 09.05.2011
comment
Это для развлечения или для решения реальной проблемы?   -  person Thorbjørn Ravn Andersen    schedule 09.05.2011
comment
Это для симулятора частиц.   -  person Caleb Jares    schedule 09.05.2011


Ответы (1)


Интересный способ инициализации LEFT и RIGHT. Попробуйте это вместо этого:

public final class PackedUnsigned1616 {
    public final int field;

    private static final int RIGHT = 0xFFFF;

    public PackedUnsigned1616(int left, int right) {
        field = (left << 16) | (right & RIGHT);
    }

    public int getLeft() {
        return field >>> 16; // >>> operator 0-fills from left
    }

    public int getRight() {
        return field & RIGHT;
    }
}

Я думаю, что для значений со знаком все, что вам нужно сделать, это изменить getLeft и getRight следующим образом:

    public int getLeft() {
        return field >> 16; // sign bit is significant
    }

    public int getRight() {
        return (short) (field & RIGHT); gets cast back to signed int
    }
person Ted Hopp    schedule 08.05.2011
comment
Спасибо! Но как мне сделать PackedSigned1616? - person Caleb Jares; 09.05.2011
comment
@Ted - я искал в Интернете нотацию 0xFFFF. Это шестнадцатеричный? Что означает 0x? Кроме того, функция getLeft для неподписанной версии не работает. Используйте значения (5, 32767), он возвращает 10 и 32727. То же самое касается (5, 32766) и (5, 27766) - person Caleb Jares; 09.05.2011
comment
@ cable729 - Обозначение 0xFFFF является шестнадцатеричным литералом. Он определен в Спецификации языка Java. Что касается неработающего кода, я исправил ошибку в своем коде (которую я унаследовал, скопировав ваш код :-0), где он смещался на 15 вместо 16. Убедитесь, что вы используете пересмотренный вариант. - person Ted Hopp; 09.05.2011
comment
Да, я тоже это нашел :) Спасибо за помощь! - person Caleb Jares; 09.05.2011
comment
Для подписанных значений вы можете вернуть short - person Peter Lawrey; 09.05.2011