я, наконец, нашел решение, это ужасно, но это работает:
public BigInteger srl(BigInteger l, int width, int shiftBy) {
if (l.signum() >= 0)
return l.shiftRight(shiftBy);
BigInteger opener = BigInteger.ONE.shiftLeft(width + 1);
BigInteger opened = l.subtract(opener);
BigInteger mask = opener.subtract(BigInteger.ONE).shiftRight(shiftBy + 1);
BigInteger res = opened.shiftRight(shiftBy).and(mask);
return res;
}
Случай, что ваше целое положительное тривиальна, поскольку shiftRight возвращает правильный результат в любом случае. Но для отрицательных чисел это становится сложно. Версия с отрицанием, упомянутая ранее, не работает, поскольку -1 в BigInteger отрицается: 1. Сдвиньте ее, и у вас есть 0. Но вам нужно знать, что такое ширина вашего BigInteger. Затем вы в основном заставляете BigInteger иметь как минимум ширину + 1 бит, вычитая открыватель. Затем вы выполняете смену и маскируете лишний бит, который вы ввели. На самом деле не имеет значения, какой нож вы используете, если он не изменяет нижние биты.
Как нож работает:
Реализация BigInteger делает только сохранить высокую 0 позицию для отрицательных чисел. -3 представлен как:
1111_1111_1111_1111_1101
Но только некоторые биты хранятся, я обозначил другие как X.
XXXX_XXXX_XXXX_XXXX_XX01
Shifting справа ничего не делает, поскольку всегда есть один приход слева , Таким образом, идея состоит в том, чтобы вычитать в 1 для создания 0 вне ширины, что вы заинтересованы в Предполагая, что вы заботитесь о самых низких двенадцати бит:.
XXXX_XXXX_XXXX_XXXX_XX01
- 0001_0000_0000_0000
========================
XXXX_XXX0_1111_1111_1101
Это заставило поколение реальных 1s. Затем вы сдвиг вправо на позволяет говорить 5.
XXXX_XXX0_1111_1111_1101
>>5 XXXX_XXX0_1111_111
А потом маскировать его:
XXXX_XXX0_1111_111
0000_0000_1111_111
И к тому же получить правильный результат:
0000_0000_1111_111
Так введение нулевой вынудила Реализация BigInteger для обновления сохраненной позиции 0 до ширины, которая выше той, которая вам интересна, и принудительно создала сохраненные 1-е.
Вы знаете, что Java не имеет перегрузки оператора, не так ли? –
Да. Я не говорю о перегрузке оператора. Разве нет способа обхода пути или метода или алгоритма для поиска операции без знака? –