Посчитать биты занимаемые числом.
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.05.03 18:43
Оценка:
Всем привет.

Можно ли без цикла посчитать количество битов требуемое для представления числа?

Ну, то есть вместо этого:

int iResidue = sizeof(array) / sizeof(array[0]);
for(; iResidue; iBits++)
{
    iResidue >>= 1;
    iBits++;
}


Написать константное выражение?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Посчитать биты занимаемые числом.
От: Павел Кузнецов  
Дата: 07.05.03 19:58
Оценка: 130 (11) +1
#Имя: FAQ.cpp.nbits
VD>Можно ли без цикла посчитать количество битов требуемое для представления числа?
VD>Ну, то есть вместо этого:

VD>
VD>int iResidue = sizeof(array) / sizeof(array[0]);
VD>for(; iResidue; iBits++)
VD>{
VD>    iResidue >>= 1;
VD>    iBits++;
VD>}
VD>


VD>Написать константное выражение?


Если предположить, что в приведенном примере один инкремент iBits++ лишний, то код может быть таким:

template<unsigned n>
struct NBits
{
  enum { value = NBits<(n >> 1)>::value + 1 };
};

template<>
struct NBits<0>
{
  enum { value = 0 };
};

unsigned iBits = NBits<sizeof(array) / sizeof(array[0])>::value;


Искомое константное выражение выделено жирным.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[2]: Посчитать биты занимаемые числом.
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.05.03 20:46
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Если предположить, что в приведенном примере один инкремент iBits++ лишний,


Нда. Копи-пэст . Я уже когда запостил, то заметил, что лажанулся. Но подумал, что на дело это не должно повлиять.

ПК>то код может быть таким:


ПК>
ПК>template<unsigned n>
ПК>struct NBits
ПК>{
ПК>  enum { value = NBits<(n >> 1)>::value + 1 };
ПК>};

ПК>template<>
ПК>struct NBits<0>
ПК>{
ПК>  enum { value = 0 };
ПК>};

ПК>unsigned iBits = NBits<sizeof(array) / sizeof(array[0])>::value;
ПК>


Бальшой сенкс!

Но я тебя еще помучаю...

А зачем нужна специализация? Ну, "NBits<0>"? Это борьба с кем-то или еще что?

И вообще, обясни принцип действия, а то я как-то не дотягиваю. Вроде все просто, но... А может к вечеру уже бошка не варит.

Кстати, сработало даже в managed-C++. Причем я даже не нашел следа от enum-а. Жаль, что в Шарпе так нельзя. Да и препроцессор они от туда зря выбрасели. Ну, да ладно. Сделают шаблоны, можно быдет такие же кренделя в рантайме отмачиать (надеюсь)...

ПК>Искомое константное выражение выделено жирным.


Ну, это и так ясно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Посчитать биты занимаемые числом.
От: Павел Кузнецов  
Дата: 08.05.03 07:50
Оценка:
Здравствуйте, VladD2, Вы писали:

ПК>>
ПК>> template<unsigned n>
ПК>> struct NBits
ПК>> {
ПК>>  enum { value = NBits<(n >> 1)>::value + 1 };
ПК>> };

ПК>> template<>
ПК>> struct NBits<0>
ПК>> {
ПК>>  enum { value = 0 };
ПК>> };

ПК>> unsigned iBits = NBits<sizeof(array) / sizeof(array[0])>::value;
ПК>>


V> А зачем нужна специализация? Ну, "NBits<0>"? Это борьба с кем-то или

V> еще что?

Это "терминальное" значение для избежания бесконечной рекурсии.

V> принцип действия


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

Вот примерный ход вычисления NBits<13>::value

NBits<13>::value = NBits<(13 >> 1)>::value + 1
                 = NBits<6>::value         + 1
                 = NBits<(6 >> 1)>::value  + 1 + 1
                 = NBits<3>::value         + 1 + 1
                 = NBits<(3 >> 1)>::value  + 1 + 1 + 1
                 = NBits<1>::value         + 1 + 1 + 1
                 = NBits<(1 >> 1)>::value  + 1 + 1 + 1 + 1
                 = NBits<0>::value         + 1 + 1 + 1 + 1
                 = 0                       + 1 + 1 + 1 + 1
                 = 4;


Если бы не было специализации NBits<0>, рекурсия бы не закончилась.

V> Кстати, сработало даже в managed-C++.


Прикольно
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re: Посчитать биты занимаемые числом.
От: MaximE Великобритания  
Дата: 08.05.03 08:26
Оценка: 10 (1)
Здравствуйте, VladD2, Вы писали:

VD>Всем привет.


VD>Можно ли без цикла посчитать количество битов требуемое для представления числа?


Если нужно в runtime, то:

floor(log2(n)) + 1;
Re[2]: Посчитать биты занимаемые числом.
От: Кодт Россия  
Дата: 08.05.03 09:29
Оценка: 12 (1)
Здравствуйте, Павел Кузнецов, Вы писали:

<>

А еще можно за логарифмическое время от разрядности числа.
Примерно так:
exp(b) = 1<<(b)
mid(l,u) = (l+u)/2
grow(u) = u*2

bits(v) =
  v == 0
    ? 0
    : bits(v,0,1)

bits(v,l,u) =
  exp(u+1) <= v
    ? bits(v,u+1,grow(u))
    :
  u == l
    ? u
    :
  exp(mid(l,u)+1) < v
    ? bits(v,mid(l,u)+1,u)
    : bits(v,l,mid(l,u))

Пример работы:
v = (1<<19)+1

bits() =
bits(0,1) =
bits(2,4) =
bits(5,8) =
bits(9,16) =
bits(17,32) =
bits(17,24) =
bits(17,20) =
bits(18,20) =
bits(19,20)

Можно сделать шаблоном
(=^.^=) Neko ... << RSDN@Home 1.0 beta 6a >>
Перекуём баги на фичи!
Re[4]: Посчитать биты занимаемые числом.
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.05.03 12:22
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Если бы не было специализации NBits<0>, рекурсия бы не закончилась.


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

V> Кстати, сработало даже в managed-C++.


ПК>Прикольно


Погано то, что мой цикл, хотя он и полностью основан на константах, VC не вычислил во время компиляции. А я как раз пишу код который должен компилироваться как в managed-, так и в unmanaged-варианте. Ну, да ладно. Впредь будем пользоваться шаблонами.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Посчитать биты занимаемые числом.
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.05.03 12:39
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Если нужно в runtime, то:


ME>
ME>floor(log2(n)) + 1;
ME>


Я уж тогда лучше циклом. Вычисления просто не соразмеримые выйдут. Да и мне нужно было именно константное решение. Заело просто, что компилятор не додумывается перевести такую фигню в константу.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Посчитать биты занимаемые числом.
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.05.03 12:39
Оценка:
Здравствуйте, Кодт, Вы писали:

Боюсь, в виду простоты вычислений в моем случае будет быстрее прогнать тупой цикл (вычисления то полевые). К тому же мне скорость если честно в данном случае не актульна. В программе производится 12 расчетов. Просто зачела неспрпведливость. Я понимаю, что вычисление ностантное (все параметры константы), а компилятор собака генерирует цикл (по кройней мере в менеджед-режиме).

В любом случае спасибо.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Посчитать биты занимаемые числом.
От: WFrag США  
Дата: 08.05.03 12:40
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, Павел Кузнецов, Вы писали:


ПК>>Если бы не было специализации NBits<0>, рекурсия бы не закончилась.


VD>И все же в голове не укладывается почему вообще начинаются рекурсивные действия. Ты же вроде задаешь конкртное значение.


Рекурсия при инстанциировании шаблона.
7. О чем невозможно говорить, о том следует молчать.
Re[4]: Посчитать биты занимаемые числом.
От: Кодт Россия  
Дата: 08.05.03 12:56
Оценка: 17 (3)
Здравствуйте, VladD2, Вы писали:

VD>Боюсь, в виду простоты вычислений в моем случае будет быстрее прогнать тупой цикл (вычисления то полевые). К тому же мне скорость если честно в данном случае не актульна. В программе производится 12 расчетов. Просто зачела неспрпведливость. Я понимаю, что вычисление ностантное (все параметры константы), а компилятор собака генерирует цикл (по кройней мере в менеджед-режиме).


Слушай, а почему бы не сделать такую страшилу:
#define _BIT(v,n) ((v) < (1<<(n))) ? (n) :

#define _BIT_4(v,n) _BIT(v,n) _BIT(v,n+1) _BIT(v,n+2) _BIT(v,n+3)
#define _BIT_8(v,n) _BIT_4(v,n) _BIT_4(v,n+4)
#define _BIT_16(v,n) _BIT_8(v,n) _BIT_8(v,n+8)
#define _BIT_32(v,n) _BIT_16(v,n) _BIT_16(v,n+16)

#define BIT(v) ( _BIT_32(v,0) 32 )

и способы работы с ним:
template<unsigned v> struct Bit
{
  enum { n = BIT(v) };
};

inline unsigned bit(unsigned v)
{
  return BIT(v);
}
(=^.^=) Neko ... << RSDN@Home 1.0 beta 6a >>
Перекуём баги на фичи!
Re[3]: Посчитать биты занимаемые числом.
От: MaximE Великобритания  
Дата: 08.05.03 13:20
Оценка:
Здравствуйте, VladD2, Вы писали:

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


ME>>Если нужно в runtime, то:


ME>>
ME>>floor(log2(n)) + 1;
ME>>


VD>Я уж тогда лучше циклом. Вычисления просто не соразмеримые выйдут. Да и мне нужно было именно константное решение. Заело просто, что компилятор не додумывается перевести такую фигню в константу.


Я всего лишь хотел сказать, что количество разрядов для представления числа N в системе исчисления с основанием R, есть 1 + округленный вниз до целого логарифм N по основанию R.
Re[5]: Посчитать биты занимаемые числом.
От: VladD2 Российская Империя www.nemerle.org
Дата: 09.05.03 01:02
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Слушай, а почему бы не сделать такую страшилу:


Да потому что вот это http://rsdn.ru/Forum/Message.aspx?mid=261504&amp;only=1
Автор: Павел Кузнецов
Дата: 07.05.03


получается проще .
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Посчитать биты занимаемые числом.
От: Кодт Россия  
Дата: 12.05.03 07:49
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Да потому что вот это http://rsdn.ru/Forum/Message.aspx?mid=261504&amp;only=1
Автор: Павел Кузнецов
Дата: 07.05.03

VD>получается проще

Зато у меня — голый Це.
И его можно использовать и в run-time (в отличие от шаблонов), и в compile-time (в отличие от функций).
(=^.^=) Neko ... << RSDN@Home 1.0 beta 6a >>
Перекуём баги на фичи!
Re[7]: Посчитать биты занимаемые числом.
От: MaximE Великобритания  
Дата: 12.05.03 07:59
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Зато у меня — голый Це.

К>И его можно использовать и в run-time (в отличие от шаблонов), и в compile-time (в отличие от функций).

Жуткая переносимость
Re[8]: Посчитать биты занимаемые числом.
От: Кодт Россия  
Дата: 12.05.03 08:34
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Жуткая переносимость


Чтобы была по-настоящему жуткая переносимость, нужно исхитриться еще для всех разрядностей (16, 32, 64).
(=^.^=) Neko ... << RSDN@Home 1.0 beta 6a >>
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.