Количество Нулей в двоичном представлении Целого числа [дубликат]

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

HTML:

<input type="file" name="FILENAME"  size="20" onchange="check_extension(this.value,"upload");"/>
<input type="submit" id="upload" name="upload" value="Attach" disabled="disabled" />

JavaScript:

var hash = {
  'xls'  : 1,
  'xlsx' : 1,
};

function check_extension(filename,submitId) {
      var re = /\..+$/;
      var ext = filename.match(re);
      var submitEl = document.getElementById(submitId);
      if (hash[ext]) {
        submitEl.disabled = false;
        return true;
      } else {
        alert("Invalid filename, please select another file");
        submitEl.disabled = true;

        return false;
      }
}
7
задан Community 23 May 2017 в 12:01
поделиться

7 ответов

Самый простой способ сделать это - перебрать каждый бит двоичного представления числа, проверить значение каждого бита и подсчитать, сколько из них равно нулю. Цикл для этого был бы намного понятнее, чем рекурсия.

Однако есть много других оптимизированных методов для этого. Вы можете найти некоторые из лучших в ответах на этот вопрос: «Лучший алгоритм для подсчета количества установленных битов в 32-битном целом числе» (очевидно, количество нулевых битов - это количество установленных битов). бит, вычитаемый из общего количества битов).

5
ответ дан 6 December 2019 в 09:20
поделиться

В Интернете есть отличный ресурс под названием Bit Twiddling Hacks , который содержит всевозможные замечательные маленькие трюки C. Вас может особенно заинтересовать раздел Набор битов счета .

5
ответ дан 6 December 2019 в 09:20
поделиться

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

Мы используем таблицу nibbles здесь, чтобы уменьшить количество запусков цикла - если вы выполняете много вычислений, было бы более эффективно построить гораздо больший массив, скажем, на уровне байтов, разрезая цикл пополам .

/* How many bits are set in every possible nibble. */
static size_t BIT_TABLE[] = {
    0, 1, 1, 2,     /* 0, 1, 2, 3 */
    1, 2, 2, 3,     /* 4, 5, 6, 7 */
    1, 2, 2, 3,     /* 8, 9, A, B */
    2, 3, 3, 4      /* C, D, E, F */
};

size_t num_of_bits(int num) {
    /* Little reworking could probably shrink the stack space in use here. */
    size_t ret = 0, i;
    register int work = num;

    /* Iterate every nibble, rotating the integer in place. */
    for(i = 0; i < (sizeof(num) * 2); i++) {
        /* Pointer math to get a member of the static array. */
        ret += *(BIT_TABLE + (work & 0xF));
        work >>= 4;
    }
    return ret;
}
4
ответ дан 6 December 2019 в 09:20
поделиться

Рекурсия определенно излишняя - и, кроме того, в вашем коде много ошибок (он не будет считать ни один из ведущих нулей num !!! ). Простая итерация, такая как:

int num_of_zero(int num) {
  unsigned int unum = (unsigned int)num;
  int count;
  int i;

  for(i = 0; i < 32; ++i) {
    if(!(unum & 1)) ++count;
    unum >>= 1;
  }
  return count;
}

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

Если вам приходится выполнять это вычисление много раз, рассмотрите возможность предварительного вычисления массива скажем) 256 «отсчетов нулей» (каждое значение дает счет для своего индекса, от 0 до 255, включая 8-битное число). Затем вы можете выполнить цикл всего 4 раза (маскируя и сдвигая 8 бит за раз) и легко развернуть цикл - если ваш компилятор недостаточно умен, чтобы сделать это от вашего имени; -).

2
ответ дан 6 December 2019 в 09:20
поделиться

На самом деле это не ответ на ваш главный вопрос, но вам следует переписать рекурсивную функцию следующим образом:

int num_of_zero(int num)
{
    int left_part_zeros;

    if (num == 0)
        return 0;

    left_part_zeros = num_of_zero(num >> 1);
    if ((num & 1) == 0)
        return left_part_zeros + 1;
    else
        return left_part_zeros;
}

У вашей реализации много проблем, помимо того, что она полностью нечитаема.

1
ответ дан 6 December 2019 в 09:20
поделиться

Самый простой способ, который я нашел, - это основать его на чем-то, что считает единицы, а затем просто вычесть это из 32 (при условии, что вы уверены int размер составляет 32 бита).

int numberOfOnes (int num) {
    int count = 0;
    unsigned int u = (unsigned int)num;
    while (u != 0) {
        if ((u&1) == 1)
            count++;
        u >>= 1;
    }
    return count;
}
int numberOfZeros (int num) {
    return 32 - numberOfOnes (num);
}

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

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

Одна возможность можно было бы заменить функцию numberOfOnes чем-то, что управляет нубайтом за раз:

int numberOfOnes (int num) {
    static const count[] = {
        0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
    };
    int retval = 0;
    unsigned int u = (unsigned int)num;
    while (u != 0) {
        retval += count[u & 0x0f]
        u >>= 4;
    }
    return retval;
}
1
ответ дан 6 December 2019 в 09:20
поделиться

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

Создайте массив из байт длиной 2 32 . Предварительно вычислите значение количества нулей в двоичном представлении для каждого возможного значения int для заполнения этого массива. С этого момента у вас будет массив, который будет давать вам количество нулей на значение.

Да, это решение глупо - это большая работа с небольшой прибылью - но объедините его с еще одной идеей:

Что произойдет, если вы просто предварительно вычислите значения длиной 8 бит? Сможете ли вы написать код, который хоть и не так быстро, все равно будет возвращать количество 0-бит в int?

Что произойдет, если вы просто предварительно вычислите значения длиной 4 бита? 2 бита? 1 бит?

Надеюсь, это даст вам идеи для лучшего алгоритма ...

2
ответ дан 6 December 2019 в 09:20
поделиться
Другие вопросы по тегам:

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