Re[3]: как узнать номер n-го установленного (1) бита внутри
От: ilnar Россия  
Дата: 28.04.03 12:21
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Здравствуйте, Кодт, Вы писали:


К>за O(N)


ME>[]


К>За O(log N) — двоичный поиск: x<>2^16? x<>2^8? и так далее.


ME>[]


ME>Я видел код (буквально пять строчек), который это делает без цикла за O(1). Вот только ссылку никак не могу найти


а идею не помните?
Re[4]: как узнать номер n-го установленного (1) бита внутри
От: ilnar Россия  
Дата: 28.04.03 12:26
Оценка:
Здравствуйте, Sergeem, Вы писали:

S>Здравствуйте, MaximE, Вы писали:


ME>Я видел код (буквально пять строчек), который это делает без цикла за O(1). Вот только ссылку никак не могу найти


S>
S>int what_bit(unsigned long x)
S>{
S>  if(x==0) return -1; // no bits
S>  if (x & (x-1)) return -2; // multiple bits

S>  return int(log(x)/log(2)); //  :shuffle: ;) 
S>}
S>


S>Как бы логарифм по основанию два извлечь без плавающей точки и за О(1)?


может я не совсем правильно выразился, перефразирую вопрос:
есть некий long
в нем установлены в разных местах битики в 1, остальные 0.
в этой последовательности необходимо найти n-й по счету установленный в 1 бит. местоположение его конечно имеет номер не меньше n.
пример:
для 1001110010... и n=4, ответ будет = 6
Re[3]: как узнать номер n-го установленного (1) бита внутри
От: ilnar Россия  
Дата: 28.04.03 12:33
Оценка:
Здравствуйте, WeCom, Вы писали:

WC>Здравствуйте, UgN, Вы писали:



WC>
UgN>char GetBitPos( long n )
WC>


WC>(риторический вопрос) А не дожен ли прототип функции быть таким? :


WC>
WC>char GetBitPos( lond tested, long n )
WC>


именно должен, т.к. внутри long может быть несколько установленных битов, мне нужно узнать n-й по счету установленный, т.е. его позиция
Re[5]: как узнать номер n-го установленного (1) бита внутри
От: ilnar Россия  
Дата: 28.04.03 12:35
Оценка:
Здравствуйте, WeCom, Вы писали:

WC>Что сказано в сабже? — "как узнать номер n-го установленного (1) бита внутри long?"

WC>Т.е. есть какое-то число (long). У него установлено несколько битов (в 1). Надо узнать номер (позицию) энного. Для n=1, задача в нахождении позиции самого правого единичного бита, для n=2 — позиции следующего единичного после самого правого, и т.д. А вы какую задачу решаете? — Найти позицию единственного единичного бита в long'е? Так это другая задача.

МОЛОТЦА, я это и имел ввиду и эту задачу и надо решить, жеоательно, если руку приложат на ассемблере
Re[4]: как узнать номер n-го установленного (1) бита внутри
От: ilnar Россия  
Дата: 28.04.03 12:40
Оценка:
Здравствуйте, Dmitry Kukushkin, Вы писали:

DK>Вообще то верно...

DK>Вот, например, так ( для intel 80486+ ) :

DK>
DK>char GetBitPos(long tested, long n)
DK>{
DK>  long i;
DK>  char pos;
DK>  for(i = 0; i < tested, n != 0; i++)
DK>  {
DK>    __asm
DK>    {
DK>       bsf eax, n
DK>       btr n, eax
DK>       mov pos, al
DK>    }
DK>  }
DK>  return i == tested ? pos : -1;
DK>}
DK>


не совсем понял, а что в eax идет и условие для for — это с tested сравнивается или с n?
Re[6]: как узнать номер n-го установленного (1) бита внутри
От: ilnar Россия  
Дата: 28.04.03 13:21
Оценка:
Здравствуйте, Dmitry Kukushkin, Вы писали:

DK>Здравствуйте, WeCom, Вы писали:


WC>Неверно. Например, GetBitPos(0xF,3) должен вернуть 2, а возвращает -1. Возможно, n и tested перепутаны местами, но GetBitPos(3,0xF) также возвращает -1.



DK>Извиняюсь...

DK>Аргументы действительно перепутаны и в цикле там малек не то...
DK>Ну вот — для ясности:

DK>
DK>char GetBitPos(long data, long n)
DK>{
DK>  int i;
DK>  char pos;
DK>  for(i = 0; i < n && data != 0; i++)
DK>  {
DK>    __asm
DK>    {
DK>       bsf eax, data
DK>       btr data, eax
DK>       mov pos, al
DK>    }
DK>  }
DK>  return i == n ? pos : -1;
DK>}
DK>


МОЛОТЦА — САМЫЙ ЛУЧШИЙ ОТВЕТ МАКСИМАЛЬНЫЙ БАЛ

позволил себе несколько изменить код (если верить TrueTime от Numega, работает намного быстрее)

char GetBitPos1(long data, long n)
{
    char i;
  char pos;
    __asm
    {
       mov ecx, n
m:
       bsf eax, data
       btr data, eax
       jz end
       mov pos, al
       loop m
end:
       cmp ecx, 0
       je m2
       mov pos, 0
m2:
    }
  
  return pos ;
}
Re: как узнать номер n-го установленного (1) бита внутри lon
От: Les Россия  
Дата: 29.04.03 15:07
Оценка: 24 (2)
Здравствуйте, ilnar, Вы писали:

I>сабж.

I>как узнать номер n-го установленного (1) бита внутри long?
I>не ли какой-либо команды процессора или какой-нибудь код для С/С++

#include "iostream.h"

//  ВАРИАНТ1
int GetBitPos( int arg, int n )
{
    //  Простой вариант. Сложность - n
    int pos = 0;
    int cnt;
    for( cnt =0; cnt<n && pos<32; pos++){
        cnt += (arg>>31) & 1;
        arg <<= 1;
    }
    if( cnt<n )
        return -1;
    else
        return pos;
}

//  ВАРИАНТ2
int GetBitPos2( unsigned int arg, int n )
{
    //  Базируется на алгоритме подсчета установленных битов в слове,
    //  было то ли в алгоритмах, то ли в этюднике
    unsigned int n1 = ((arg& 0xAAAAAAAA) >> 1 ) + (arg& 0x55555555);
    unsigned int n2 = ((n1 & 0xCCCCCCCC) >> 2 ) + (n1 & 0x33333333);
    unsigned int n3 = ((n2 & 0xF0F0F0F0) >> 4 ) + (n2 & 0x0F0F0F0F);
    unsigned int n4 = ((n3 & 0xFF00FF00) >> 8 ) + (n3 & 0x00FF00FF);
    unsigned int n5 = ((n4 & 0xFFFF0000) >> 16) + (n4 & 0x0000FFFF);

    //  n5 - общее кол-во установленных битов


    if (n5 < n)
        return -1;
    if (!n)
        return 0;
    
    //  Ищем спускаясь по двоичному дереву. Сложность - log(n)

    int pos;
    unsigned int mask = 0xFFFF0000;
    int leftHalf = (n4 & mask) >> 16;

    if ( n > leftHalf){            
        pos = 16;                   //  Вправо
        n -= leftHalf;
        mask >>= 16;
    }
    else{
        pos = 0;                    //  Влево
    }

    mask &= 0xFF00FF00;
    leftHalf = (n3 & mask) >> (32-pos-8);

    if ( n > leftHalf){            
        pos += 8;                   //  Вправо
        n -= leftHalf;
        mask >>= 8;
    }

    mask &= 0xF0F0F0F0;
    leftHalf = (n2 & mask) >> (32-pos-4);

    if ( n > leftHalf){            
        pos += 4;                   //  Вправо
        n -= leftHalf;
        mask >>= 4;
    }

    mask &= 0xCCCCCCCC;
    leftHalf = (n1 & mask) >> (32-pos-2);

    if ( n > leftHalf){            
        pos += 2;                   //  Вправо
        n -= leftHalf;
        mask >>= 2;
    }

    mask &= 0xAAAAAAAA;
    leftHalf = (arg & mask) >> (32-pos-1);

    if ( n > leftHalf){            
        pos += 1;                   //  Вправо
        n -= leftHalf;
        mask >>= 1;
    }
    return pos+1;
}

//  ТЕСТ
int main(int argc, char* argv[])
{
    printf("Hello World!\n");

    cout << GetBitPos ( 0, 0 ) << "\n";
    cout << GetBitPos ( 0xFF00FF00, 1 ) << "\n";
    cout << GetBitPos ( 0xFF00FF00, 3 ) << "\n";
    cout << GetBitPos ( 0xFF00FF00, 9 ) << "\n";
    cout << GetBitPos ( 0xFF00FF00, 20) << "\n";
    cout << GetBitPos2( 0, 0 ) << "\n";
    cout << GetBitPos2( 0xFF00FF00, 1 ) << "\n";
    cout << GetBitPos2( 0xFF00FF00, 3 ) << "\n";
    cout << GetBitPos2( 0xFF00FF00, 9 ) << "\n";
    cout << GetBitPos2( 0xFF00FF00, 20) << "\n";
    
    flush(cout);

    unsigned int i;
    int r=0;

    for(i=0;i<10000000;i++){
        r+=GetBitPos( i, i % 16);
    }

    cout << r << "\n";
    flush(cout);
    r = 0;

    for(i=0;i<10000000;i++){
        r+=GetBitPos2( i, i % 16);
    }

    cout << r << "\n";
    flush(cout);

    return 0;
}

Работает! Самое смешное, второй вариант действительно быстрее (int32, x86, vc60) % на 30. ilnar, с тебя пузырь! Вообще то, если использовать встроенную инструкцию поиска первого бита, будет конечно быстрее. Зато так переносимо. И соответствует форуму. И вообще круче.
Re[2]: как узнать номер n-го установленного (1) бита внутри
От: ilnar Россия  
Дата: 29.04.03 15:23
Оценка:
Здравствуйте, Les, Вы писали:

Les>Здравствуйте, ilnar, Вы писали:

Les>Работает! Самое смешное, второй вариант действительно быстрее (int32, x86, vc60) % на 30. ilnar, с тебя пузырь! Вообще то, если использовать встроенную инструкцию поиска первого бита, будет конечно быстрее. Зато так переносимо. И соответствует форуму. И вообще круче.

а мне совсем не смешно от того, что операции С/С++ намного урезают операции процессора, иногда смотришь команды процессора и видишь, что то, что я пишу на С — на самом-то деле выполняется одной операцией процессора.

Соответствие форуму у ассемблера тоже есть по двум причинам:
— хотел получиь лаконичный ответ на С/С++
— ассемблерные вставки описаны в этих языках

кстати, gcc уже поддерживает формат записи ассемблера как у майкрасофта,
а переносимость на другие аппаратные платформы и не собираюсь
Re: как узнать номер n-го установленного (1) бита внутри lon
От: Artem_Sh  
Дата: 29.04.03 17:16
Оценка:
Здравствуйте, ilnar, Вы писали:

I>сабж.

I>как узнать номер n-го установленного (1) бита внутри long?
I>не ли какой-либо команды процессора или какой-нибудь код для С/С++
для этого есть шаблон std::bitset.
Re[3]: как узнать номер n-го установленного (1) бита внутри
От: Sergeem Израиль  
Дата: 30.04.03 08:32
Оценка:
Здравствуйте, ilnar, Вы писали:

...

I>кстати, gcc уже поддерживает формат записи ассемблера как у майкрасофта,

I>а переносимость на другие аппаратные платформы и не собираюсь

не зарекайтесь!
завтра (вспомните закон Мура) выйдет новый супер-пупер 137-битный процессор
у которого родной istruction set будет в 10 раз быстрее чем ваши х86 ассемблерные
вставки. Что, будете каждый раз код переписывать?
Serge.

Hасколько проще была бы жизнь, если бы она была в исходниках.
Re[4]: как узнать номер n-го установленного (1) бита внутри
От: ilnar Россия  
Дата: 30.04.03 11:02
Оценка:
Здравствуйте, Sergeem, Вы писали:

S>Здравствуйте, ilnar, Вы писали:


S>...


I>кстати, gcc уже поддерживает формат записи ассемблера как у майкрасофта,

I>а переносимость на другие аппаратные платформы и не собираюсь

S>не зарекайтесь!

S>завтра (вспомните закон Мура) выйдет новый супер-пупер 137-битный процессор
S>у которого родной istruction set будет в 10 раз быстрее чем ваши х86 ассемблерные
S>вставки. Что, будете каждый раз код переписывать?

скжау 2 вещи:
1. языки высокого уровня всегда урезают возможности процессора для реализации какой-либо операции.
2. я найду время переписать код в 10 строк, зато программа будет быстрее намного работать
Re: как узнать номер n-го установленного (1) бита внутри lon
От: impaler  
Дата: 30.04.03 11:55
Оценка: :)))
Здравствуйте, ilnar, Вы писали:

I>сабж.

I>как узнать номер n-го установленного (1) бита внутри long?
I>не ли какой-либо команды процессора или какой-нибудь код для С/С++


Так вот, надо создать базу данных всех чисел типа long где для каждого бита каждого числа будет храниться значение, указывающее, установлен он в 1 или в 0. Теперь при необходимости можно выполнить SQL-запрос и получить полную информацию о каждом бите нужного числа
Re[2]: как узнать номер n-го установленного (1) бита внутри
От: Аноним  
Дата: 30.04.03 11:58
Оценка:
Здравствуйте, impaler, Вы писали:

I>Так вот, надо создать базу данных всех чисел типа long где для каждого бита каждого числа будет храниться значение, указывающее, установлен он в 1 или в 0. Теперь при необходимости можно выполнить SQL-запрос и получить полную информацию о каждом бите нужного числа


Что ж, это максимально гибко. А при необходимости битовое представление чисел можно будет даже и менять!
Re[2]: как узнать номер n-го установленного (1) бита внутри
От: Юнусов Булат Россия  
Дата: 30.04.03 17:31
Оценка:
Здравствуйте, Artem_Sh, Вы писали:

A_S>для этого есть шаблон std::bitset.


Согласен, правда boost::dynamic_bitset удобнее (размер в рантайме задавать можно)
Re[3]: как узнать номер n-го установленного (1) бита внутри
От: skyline Россия  
Дата: 02.05.03 08:26
Оценка: 9 (1)
Могу предложить еще один вариант.
typedef struct __My_bitset
{
unsigned f_0:1 ;
unsigned f_1:1 ;
unsigned f_2:1 ;
unsigned f_3:1 ;
unsigned f_4:1 ;
unsigned f_5:1 ;
unsigned f_6:1 ;
unsigned f_7:1 ;
unsigned f_8:1 ;
unsigned f_9:1 ;
unsigned f_10:1 ;
unsigned f_11:1 ;
unsigned f_12:1 ;
unsigned f_13:1 ;
unsigned f_14:1 ;
unsigned f_15:1 ;
unsigned f_16:1 ;
unsigned f_17:1 ;
unsigned f_18:1 ;
unsigned f_19:1 ;
unsigned f_20:1 ;
unsigned f_21:1 ;
unsigned f_22:1 ;
unsigned f_23:1 ;
unsigned f_24:1 ;
unsigned f_25:1 ;
unsigned f_26:1 ;
unsigned f_27:1 ;
unsigned f_28:1 ;
unsigned f_29:1 ;
unsigned f_30:1 ;
unsigned f_31:1 ;
} My_bitset ;

union My_B2L
{
long f_L ;
My_bitset f_bits ;
};

и копируй в первое поле long, получишь во втором битовый массив.

Кстати, что за зверь boost::dynamic_bitset ?
If the milk turns out to be sour,
I ain't the kind of pussy to drink it
Re[4]: как узнать номер n-го установленного (1) бита внутри
От: MaximE Великобритания  
Дата: 02.05.03 09:58
Оценка:
Здравствуйте, skyline, Вы писали:

S>Кстати, что за зверь boost::dynamic_bitset ?
Re[4]: как узнать номер n-го установленного (1) бита внутри
От: MaximE Великобритания  
Дата: 02.05.03 09:58
Оценка:
Здравствуйте, skyline, Вы писали:

S>Кстати, что за зверь boost::dynamic_bitset ?


Description
The dynamic_bitset class represents a set of bits. It provides accesses to the value of individual bits via an operator[] and provides all of the bitwise operators that one can apply to builtin integers, such as operator& and operator<<. The number of bits in the set is specified at runtime via a parameter to the constructor of the dynamic_bitset.

The dynamic_bitset class is nearly identical to the std::bitset class. The difference is that the size of the dynamic_bitset (the number of bits) is specified at run-time during the construction of a dynamic_bitset object, whereas the size of a std::bitset is specified at compile-time through an integer template parameter.

The main problem that dynamic_bitset is designed to solve is that of representing a subset of a finite set. Each bit represents whether an element of the finite set is in the subset or not. As such the bitwise operations of dynamic_bitset, such as operator& and operator|, correspond to set operations, such as intersection and union.

Re[5]: как узнать номер n-го установленного (1) бита внутри
От: skyline Россия  
Дата: 02.05.03 11:46
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Здравствуйте, skyline, Вы писали:


S>Кстати, что за зверь boost::dynamic_bitset ?


Я хотел спросить, это что: приблуда к C или приблуда к какому-то компилятору — а то у меня в MSDN нет ничего на эту тему. Судя по описанию, это неплохой механизм.
If the milk turns out to be sour,
I ain't the kind of pussy to drink it
Re[6]: как узнать номер n-го установленного (1) бита внутри
От: LCR Россия lj://_lcr_
Дата: 02.05.03 13:44
Оценка:
Здравствуйте, skyline, Вы писали:

S>Я хотел спросить, это что: приблуда к C или приблуда к какому-то компилятору ...


Это просто библиотека классов (см на sourceforge).
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[6]: как узнать номер n-го установленного (1) бита внутри
От: WFrag США  
Дата: 02.05.03 13:52
Оценка:
Здравствуйте, skyline, Вы писали:

S>Здравствуйте, MaximE, Вы писали:


ME>>Здравствуйте, skyline, Вы писали:


S>>Кстати, что за зверь boost::dynamic_bitset ?


S>Я хотел спросить, это что: приблуда к C или приблуда к какому-то компилятору — а то у меня в MSDN нет ничего на эту тему. Судя по описанию, это неплохой механизм.


Это набор всяких разных дополнительных библиотек к C++, обладает довольно богатыми возможностями (кстати, может частично войдет в будущий стандарт STL).

Смотри тут: www.boost.org
... << RSDN@Home 1.0 beta 6a >>
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.