Проверьте, установлен ли бит в BigNum

#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, если вы используете многобайтовые строки, вы получите очень странные результаты.