Подсчет, инвертированная комбинация двоичных разрядов

Java позволяет объектам реализовать метод finalize (), который может быть вызван.

метод finalize () вызывается, если сборщик мусора пытается собрать объект.

Если сборщик мусора не запускается, метод не вызывается.

Если сборщик мусора не может собрать объект и пытается запустить его снова, метод не будет вызван в во второй раз.

На практике вы вряд ли сможете использовать его в реальных проектах.

Просто имейте в виду, что он не может быть вызван и что он определенно не будет дважды. Метод finalize () может начинаться с нуля или один раз.

В следующем коде метод finalize () не выводит результат, когда мы запускаем его с момента выхода программы, прежде чем возникнет необходимость запуска сборщика мусора.

blockquote>

Источник

7
задан juan 3 November 2008 в 19:29
поделиться

10 ответов

Это, я думаю самый легкий с битовыми операциями, даже при том, что Вы сказали, что это не было предпочтено

При принятии 32 битов ints, вот изящный блок кода, который может инвертировать все биты, не делая его на 32 шагах:

 unsigned int i;
 i = (i & 0x55555555) <<  1 | (i & 0xaaaaaaaa) >>  1;
 i = (i & 0x33333333) <<  2 | (i & 0xcccccccc) >>  2;
 i = (i & 0x0f0f0f0f) <<  4 | (i & 0xf0f0f0f0) >>  4;
 i = (i & 0x00ff00ff) <<  8 | (i & 0xff00ff00) >>  8;
 i = (i & 0x0000ffff) << 16 | (i & 0xffff0000) >> 16;
 i >>= (32 - n);

По существу это делает чередованную перестановку всех битов. Каждый раз приблизительно половина битов в значении подкачиваются с другой половиной.

Последняя строка необходима для перестройки битов так, чтобы мусорное ведро "n" было старшим значащим битом.

Более короткие версии этого возможны, если "n" <= 16, или <= 8

3
ответ дан 7 December 2019 в 05:33
поделиться
void reverse(int nMaxVal, int nBits)
{
   int thisVal, bit, out;

   // Calculate for each value from 0 to nMaxVal.
   for (thisVal=0; thisVal<=nMaxVal; ++thisVal)
   {
      out = 0;

      // Shift each bit from thisVal into out, in reverse order.
      for (bit=0; bit<nBits; ++bit)
         out = (out<<1) + ((thisVal>>bit) & 1)

   }
   printf("%d -> %d\n", thisVal, out);
}
0
ответ дан 7 December 2019 в 05:33
поделиться

Это решение было первоначально в двоичном файле и преобразовало в стандартную математику как указанная запрашивающая сторона.

Это имело бы больше смысла как двоичный файл, по крайней мере, умножение на 2 и разделилось бы на 2, должен быть <<1 и>> 1 для скорости, дополнения и вычитания, вероятно, не имеют значения так или иначе.

Если Вы будете передавать в маске вместо nBits, и использовать bitshifting вместо того, чтобы умножиться или разделиться, и изменять хвостовую рекурсию на цикл, то это, вероятно, будет самым производительным решением, которое Вы найдете начиная с любого вызова, это будет только сингл, добавляют, это только было бы столь же медленно как решение Alnitak один раз в 4, возможно, даже 8 вызовов.

int incrementBizarre(int initial, int nBits)
    // in the 3 bit example, this should create 100
    mask=2^(nBits-1)
    // This should only return true if the first (least significant) bit is not set
    // if initial is 011 and mask is 100
    //                3               4, bit is not set
    if(initial < mask)
        // If it was not, just set it and bail.
        return initial+ mask // 011 (3) + 100 (4) = 111 (7)
    else
        // it was set, are we at the most significant bit yet?
        // mask 100 (4) / 2 = 010 (2), 001/2 = 0 indicating overflow
        if(mask / 2) > 0
            // No, we were't, so unset it (initial-mask) and increment the next bit
            return incrementBizarre(initial - mask, mask/2)
        else
            // Whoops we were at the most significant bit.  Error condition
            throw new OverflowedMyBitsException()

Ничего себе, это оказалось довольно прохладным. Я не фигурировал в рекурсии до прошлой секунды там.

Это чувствует себя неправильным - как существуют некоторые операции, которые не должны работать, но они делают из-за природы того, что Вы делаете (как он, чувствует, что необходимо попасть в беду, когда Вы воздействуете на немного, и некоторые биты налево являются ненулевыми, но оказывается, что Вы никогда не можете воздействовать на немного, если все биты налево не являются нулем - который является очень странным условием, но верный.

Пример потока для получения от 110 до 001 (назад 3 к назад 4):

mask 100 (4), initial 110 (6); initial < mask=false; initial-mask = 010 (2), now try on the next bit
mask 010 (2), initial 010 (2); initial < mask=false; initial-mask = 000 (0), now inc the next bit
mask 001 (1), initial 000 (0); initial < mask=true;  initial + mask = 001--correct answer
2
ответ дан 7 December 2019 в 05:33
поделиться

На каждом шаге найдите крайние левые 0 цифр своего значения. Установите его и очистите все цифры слева от него. Если Вы не находите 0 цифр, то Вы переполнились: возвратитесь 0, или остановка или катастрофический отказ, или независимо от того, что Вы хотите.

Это - то, что происходит на нормальном двоичном инкременте (которым я подразумеваю, что это - эффект, не, как это реализовано в аппаратных средствах), но мы делаем его слева вместо права.

Делаете ли Вы это в разрядной операции в секунду, строки, или что бы то ни было, ваше дело. Если Вы делаете это в bitops, то clz (или звонят в эквивалентную функцию hibit-стиля) на ~value мог бы быть самый эффективный путь: __ builtin_clz где это возможно. Но это - деталь реализации.

2
ответ дан 7 December 2019 в 05:33
поделиться

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

sub reverse_increment {
  my($n, $bits) = @_;

  my $carry = 2**$bits;
  while($carry > 1) {
    $carry /= 2;
    if($carry > $n) {
      return $carry + $n;
    } else {
      $n -= $carry;
    }
  }
  return 0;
}
0
ответ дан 7 December 2019 в 05:33
поделиться

Возможно, инкремент от 0 до N ("обычный" путь") и делает ReverseBitOrder () для каждого повторения. Можно найти несколько реализаций здесь (мне нравится LUT один лучшее). Должно быть действительно быстрым.

0
ответ дан 7 December 2019 в 05:33
поделиться

Вот решение, которое на самом деле не пытается сделать любое дополнение, но использует шаблон включения - выключения seqence (разрядные альтернативы большей части сигнала каждый раз, затем разрядные альтернативы большей части сигнала, каждое второе время, и т.д.), корректируют n, как желаемый:

#define FLIP(x, i) do { (x) ^= (1 << (i)); } while(0)

int main() {
    int n   = 3;
    int max = (1 << n);
    int x   = 0;

    for(int i = 1; i <= max; ++i) {
        std::cout << x << std::endl;
        /* if n == 3, this next part is functionally equivalent to this:
         *
         * if((i % 1) == 0) FLIP(x, n - 1);
         * if((i % 2) == 0) FLIP(x, n - 2);
         * if((i % 4) == 0) FLIP(x, n - 3);
         */
        for(int j = 0; j < n; ++j) {
            if((i % (1 << j)) == 0) FLIP(x, n - (j + 1));
        }                       
    }
}
0
ответ дан 7 December 2019 в 05:33
поделиться

Позвольте принимают номер 1110101, и наша задача состоит в том, чтобы найти следующий.

1) Находят нуль на самом высоком положении и отмечают позицию как индекс .

111 0 1010 (4-е положение, таким образом индекс = 4)

2) Обнуленный все биты на положении выше, чем индекс .

000 01010

3) Изменение основанный нуль от шага 1) к '1'

000 1 1010

Вот именно. Это - безусловно самый быстрый алгоритм, так как большая часть CPU имеет инструкции достигнуть этого очень эффективно. Вот реализация C++, которые увеличивают число на 64 бита в обратном шаблоне.

#include <intrin.h>
unsigned __int64 reversed_increment(unsigned __int64 number) 
{
  unsigned long index, result;
  _BitScanReverse64(&index, ~number); // returns index of the highest '1' on bit-reverse number (trick to find the highest '0')
  result = _bzhi_u64(number, index); // set to '0' all bits at number higher than index position
  result |= (unsigned __int64) 1 << index; // changes to '1' bit on index position
  return result;
}

не поражает Ваши требования, чтобы не начать "биты" операции, однако я боюсь, что существует теперь путь, как достигнуть чего-то подобного без них.

0
ответ дан 7 December 2019 в 05:33
поделиться

С n как Ваше питание 2 и x переменная Вы хотите ступить:

(defun inv-step (x n)       ; the following is a function declaration
  "returns a bit-inverse step of x, bounded by 2^n"    ; documentation
  (do ((i (expt 2 (- n 1))  ; loop, init of i
          (/ i 2))          ; stepping of i
       (s x))               ; init of s as x
      ((not (integerp i))   ; breaking condition
       s)                   ; returned value if all bits are 1 (is 0 then)
    (if (< s i)                         ; the loop's body: if s < i
        (return-from inv-step (+ s i))  ;     -> add i to s and return the result
        (decf s i))))                   ;     else: reduce s by i

Я прокомментировал это полностью, поскольку Вы не можете быть знакомы с этим синтаксисом.

править: вот является хвост рекурсивной версией. Это, кажется, немного быстрее, при условии, что у Вас есть компилятор с оптимизацией последнего вызова.

(defun inv-step (x n)
  (let ((i (expt 2 (- n 1))))
    (cond ((= n 1)
           (if (zerop x) 1 0))         ; this is really (logxor x 1)                                                 
          ((< x i)
           (+ x i))
          (t
           (inv-step (- x i) (- n 1))))))
0
ответ дан 7 December 2019 в 05:33
поделиться

Как насчет того, чтобы добавить 1 к старшему значащему биту, затем неся к следующему (менее значительному) биту, при необходимости. Вы могли ускорить это путем работы на байты:

  1. Предварительно вычислите справочную таблицу для подсчета в разрядном реверсе от 0 до 256 (00000000-> 10000000, 10000000-> 01000000..., 11111111-> 00000000).
  2. Установите все байты в своем многобайтовом числе для обнуления.
  3. Увеличьте старший значащий байт с помощью справочной таблицы. Если байт 0, увеличьте следующий байт с помощью справочной таблицы. Если байт 0, увеличьте следующий байт...
  4. Перейдите к шагу 3.
0
ответ дан 7 December 2019 в 05:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: