какой метод битовых манипуляций более эффективен в C? - PullRequest
0 голосов
/ 07 января 2011

Основываясь на ответах, которые я получил, я думаю, что эта проблема бессмысленна. Спасибо за все ваши добрые ответы!

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

1. ~(~0 << j)
2. (1 << j) - 1

Ответы [ 8 ]

3 голосов
/ 07 января 2011

Не уверен, что это именно тот ответ, который вы ищете, но держу пари, что разница не превысит наносекунду.:)

Или, другими словами: не оптимизируйте микро, если только одна строка не является узким местом в вашем коде.

Если вам нужно другое формы быстрых битовых манипуляций, которые на самом деле могут быть медленнее, попробуйте взглянуть на встроенные функции компилятора, например _BitScanForward.Это может на самом деле ускорить ваши битовые операции при правильном использовании (но не в такой ситуации).

2 голосов
/ 07 января 2011

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

1 голос
/ 07 января 2011

Если вы не измените 0 на 0U, выражение ~(~0 << j) будет вести себя в зависимости от реализации на основе битовых комбинаций. С другой стороны, выражение (1 << j) - 1 является чисто арифметическим и не содержит арифметических битов, поэтому его значение четко определено во всех реализациях. Поэтому я бы всегда пользовался последним.

1 голос
/ 07 января 2011

Если вы действительно хотите, чтобы самый быстрый , используйте таблицу поиска:

const unsigned numbers[] = {
        0x00000000,
        0x00000001, 0x00000003, 0x00000007, 0x0000000f,
        0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff,
        0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff,
        0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
        0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff,
        0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff,
        0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff,
        0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff};

unsigned h(unsigned j) {
        return numbers[j];
}

Расширение этого до 64 битов оставлено в качестве упражнения для читателя.И, как говорили другие, все это не имеет значения.

1 голос
/ 07 января 2011

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

#include <ctime>
main()
{
  int i;
  time_t start = time();
  for (i = 0; i < 1000000; i++)
  {
    // your operation here
  }
  time_t stop = time();
  double elapsed = difftime(stop, start);
}
1 голос
/ 07 января 2011

В дополнение к уже опубликованным комментариям:

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

0 голосов
/ 07 января 2011

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

0 голосов
/ 07 января 2011

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

...