#bitwise-operators #bignum #arbitrary-precision
#побитовые операторы #bignum #произвольная точность
Вопрос:
У меня есть размер, отформатированный в виде строки, подобной этой: «123456789123456789123456789», и мне нужно проверить, установлен ли указанный бит. Компоненты представляют собой отдельные цифры в этой строке.
Обычно я бы сделал это так, если бы хотел проверить, установлен ли бит 54: NyNumberamp;(1<<54)
Проблема в том, что у меня нет AND или SHIFT в библиотеке bignum, которую я использую.
Итак, вопрос в том, как я могу проверить, установлен ли бит в числе, отформатированном как строка произвольного размера?
Редактировать: просто для пояснения: я использую небольшой язык сценариев под названием Autoit3 со следующей библиотекой: http://www.autoitscript.com/forum/topic/83529-bignum-udf который представляет БигНумы в виде строк.
Ответ №1:
Прежде всего, вы можете (и должны) использовать библиотеку для обработки чисел произвольной точности.
В java у вас есть BigInteger , а в C вы можете использовать Gnu Big Num
Если вы не хотите этого делать (и я предполагаю, что вы не ищете производительность), вы можете:
-
преобразуйте строку в ее двухкомпонентное представление и проверьте индекс.
-
создайте побитовую операцию и и преобразуйте строку с двоичным представлением нужного вам индекса (например, «0100») в базовое значение 10.
-
Сдвиг битов такой же, как деление на два, поэтому, если вы хотите сдвинуть 54 бита, вы должны разделить число на 2 ^ 54. Затем вы можете просто проверить, является ли число четным или нечетным, если оно четное, то бит не установлен.
Если вы используете последний метод, вы можете сделать что-то вроде:
bool bitCheck (number, bitIndex)
pow = 2^bitIndex
shifted = number / pow
return (shifted % 2) == 0
ps: Если вы используете gmp, вы можете проверить эту страницу
Ответ №2:
Преобразуйте вашу строку в двоичную строку, а затем проверьте 54-й индекс. Для java вместо этого вы можете попробовать BigInteger
class .
BigInteger bi = new BigInteger("123456789123456789123456789");
boolean hasBitSet = bi.equals(bi.setBit(54));
Редактировать:
byte[] b = "123456789123456789123456789".getBytes("US-ASCII");
int maxIndex = b.length - 1;
for (int bitIdx = 0; bitIdx < (b.length * 8); bitIdx ) {
int index = maxIndex - (bitIdx / 8);
int remainder = bitIdx % 8;
boolean hasBitSet = (((b[index] amp; 0xff)) amp; (1 << remainder)) != 0;
System.out.println( bitIdx (hasBitSet ? " has set" : " has not set") );
}
Комментарии:
1. Я использую не Java, а небольшой язык без поддержки bignum. Я думал о преобразовании его в двоичную строку, но это кажется неэффективным, поскольку длина строки может составлять несколько сотен цифр. Разве нельзя было бы вычислить, какой компонент соответствует конкретному биту, и выполнить обычное И на нем?
2. @monoceres: найдите индекс байта: длина строки — 54/8 (частное) — 1 (если 54/8 имеет остаток). затем сравните бит (8 — остаток от 54/8) с символом в индексе. я предполагаю, что символы имеют размер 1 байт.
3. Это работает только в том случае, если вы используете строки ascii, если вы используете многобайтовые строки, вы получите очень странные результаты.