Jump to content
    

Как выделить биты в байте

Допустим есть случайное число байт, нужно из него получить число, в котором будет заранее определенной кол-во единиц, например 1, 2, 3

Как такое можно наиболее просто сделать ?

Также можно сформулировтаь по другому - как получить байт, в котором будет заданное кол-во бит=1 , расположенных случайном образом в байте

Edited by whale

Share this post


Link to post
Share on other sites

On 3/18/2023 at 6:39 PM, whale said:

как получить байт, в котором будет заданное кол-во бит=1 , расположенных случайном образом в байте

Сделать таблицу на 56 строк (если кол-во единиц равно 3) и обращаться к ней по случайному адресу.

Share this post


Link to post
Share on other sites

48 minutes ago, whale said:

как получить байт, в котором будет заданное кол-во бит=1 , расположенных случайном образом в байте

uint8_t result = 0;
for (bits_cnt = 0; bits_cnt < 3; ) {
  shift = rand() % 8;
  if ((result & (1ul << shift)) == 0) {
    result |= 1ul << shift;
    bit_cnt++;
  }
}

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

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

Edited by engel65536

Share this post


Link to post
Share on other sites

Делаете массив на 8 байтов, заполняете в нём подряд нужное количество единиц, хвост заполняете нулями. Затем запукаете на него std::random_shuffle. Затем сворачиваете массив в байт.

 

Можно и сразу в байте сделать, но тогда вам придётся изобрести итератор на бит.

 

Share this post


Link to post
Share on other sites

3 hours ago, engel65536 said:

Генерим случайную величину сдвига

Да, такое я думал, это решение в лоб, может как то еще проще/быстрее ?

2 hours ago, xvr said:

Делаете массив на 8 байтов

Что то совсем сложно.

 

Короче надо рисовать шум в заданной области с разной плотностью на экране ssd1306 а  там ввод точек идет по столбцам в байт.

Edited by whale

Share this post


Link to post
Share on other sites

7 часов назад, whale сказал:

как получить байт, в котором будет заданное кол-во бит=1 , расположенных случайном образом в байте

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

Делаете девять массивов, для хранения значений байт:
В первом массиве - значения, где 1 единица в байте;
Во втором массиве - значения, где 2 единицы в байте;
В третьем массиве - значения, где 3 единицы в байте;
...
В девятом массиве - значения, где нет единиц в байте;

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

Когда вам нужно сгенерировать значение байта - берете случайный элемент из нужного массива.

Share this post


Link to post
Share on other sites

13 hours ago, whale said:

Что то совсем сложно.

 

🤪

char get_rnd_byte(int total_ones)
{
	bool buf[8];
  
	for(int i=0; i<8; ++i) buf[i] = i < total_ones;
  
	std::random_shuffle(buf, buf+8);

	char result = 0;
	for(int i=0; i<8; ++i) result = (result << 1) | buf[i];
  
    return result;
}

 

13 hours ago, whale said:

Короче надо рисовать шум в заданной области с разной плотностью на экране ssd1306 а  там ввод точек идет по столбцам в байт.

При рисовании побайтно у вас шум будет полосатым 🙂. И плотность менее 1/8 сделать не получится. Генерите сразу строку (моим алгоритмом вполне можно сгенерить, хоть всю картинку сразу)

 

Share this post


Link to post
Share on other sites

20 часов назад, whale сказал:

Короче надо рисовать шум в заданной области с разной плотностью на экране

Так и надо было сразу говорить. Для такой задачи совсем не нужно формировать точное число единиц в байтах. Достаточно завести некую переменную, которая будет управлять генератором случайных чисел, повышая или понижая среднюю плотность потока единиц в числах идущих с него. И каждое полученное число - выдавать на экран, а также считать число единиц в нём и увеличивать/уменьшать нашу переменную. Тогда можно очень быстро генерировать поток случайных данных с заданным средним удельным количеством "1" в нём.

Примерно так:

enum {FILTER_ORDER = 5};   //значение порядка фильтра - подобрать
u32 j = N << FILTER_ORDER; //начальное значение управляющей переменной; где: N - среднее требуемое кол-во единиц в слове
uint n = размер_видеобуфера_в_словах;
do {
  u32 i = funcRnd(j);  //функция генерит случайное число, со средней вероятностью "1" == (j >> FILTER_ORDER)
  вывод_пачки_точек_на_экран(i);
  i = функция_подсчитывающая_число_единиц_в_слове(i);
  j += i - (j >> FILTER_ORDER);
} while (--n);

Обратная связь будет всегда тянуть скользящий фильтр к идеальному == (N << FILTER_ORDER), плавно регулируя количество "1" в выводе.

funcRnd() тут не обязана генерить жёстко заданное число единиц. Достаточно чтобы просто число единиц в её выводе росло с уменьшением аргумента; и падало с его ростом. Это сделать нетрудно.

 

PS: А попытки фиксировать число единиц в байте фиксированным значением, приведут к полосатости на экране. Как уже выше заметили.

Share this post


Link to post
Share on other sites

1 hour ago, jcxz said:

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

Не пойму откуда полосатость ?

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

По моему вариант с массивом самый быстрый и прозрачный. 

9 hours ago, xvr said:

Генерите сразу строку

Попробую хотя срока там от 1 столбца до 128, меняется.

 

ps хотя да, наверно будет некая полосатость, особено если будет по одной единице в байте.

 

Упростим  задачу, 

есть часть строки из n байт (от 1 - 128), те массив из n байт, каждый бит в котором отображает точку.

нужно в этот массив байт записать белый шум, 

потом весь массив тупо выводим на дисплей.

 

Edited by whale

Share this post


Link to post
Share on other sites

14 hours ago, whale said:

те чтобы между точками была по меньшей мере одна нулевая точка.

Тогда макисмальный коэфициент заполнения - 50%

14 hours ago, whale said:

нужно в этот массив байт записать белый шум, 

 

Мой алгоритм (только надо убрать промежуточный массив и сразу работать на массиве битов) или алгоритм от jcxz

Share this post


Link to post
Share on other sites

6 hours ago, xvr said:

Тогда макисмальный коэфициент заполнения - 50%

Мой алгоритм (только надо убрать промежуточный массив и сразу работать на массиве битов) или алгоритм от jcxz

Решу проблеммы с прерыванием и попробую.

Edited by whale

Share this post


Link to post
Share on other sites

вот массив отсортированный по возрастанию количества 1 в байте.

const series[256] = {0, 1, 2, 4, 8, 16, 32, 64, 128, 3, 5, 6, 9, 10, 12, 17, 18, 20, 24, 33, 34, 36, 40, 48, 65, 66, 68, 72, 80, 96, 129, 130, 132, 136, 144, 160, 192, 7, 11, 13, 14, 19, 21, 22, 25, 26, 28, 35, 37, 38, 41, 42, 44, 49, 50, 52, 56, 67, 69, 70, 73, 74, 76, 81, 82, 84, 88, 97, 98, 100, 104, 112, 131, 133, 134, 137, 138, 140, 145, 146, 148, 152, 161, 162, 164, 168, 176, 193, 194, 196, 200, 208, 224, 15, 23, 27, 29, 30, 39, 43, 45, 46, 51, 53, 54, 57, 58, 60, 71, 75, 77, 78, 83, 85, 86, 89, 90, 92, 99, 101, 102, 105, 106, 108, 113, 114, 116, 120, 135, 139, 141, 142, 147, 149, 150, 153, 154, 156, 163, 165, 166, 169, 170, 172, 177, 178, 180, 184, 195, 197, 198, 201, 202, 204, 209, 210, 212, 216, 225, 226, 228, 232, 240, 31, 47, 55, 59, 61, 62, 79, 87, 91, 93, 94, 103, 107, 109, 110, 115, 117, 118, 121, 122, 124, 143, 151, 155, 157, 158, 167, 171, 173, 174, 179, 181, 182, 185, 186, 188, 199, 203, 205, 206, 211, 213, 214, 217, 218, 220, 227, 229, 230, 233, 234, 236, 241, 242, 244, 248, 63, 95, 111, 119, 123, 125, 126, 159, 175, 183, 187, 189, 190, 207, 215, 219, 221, 222, 231, 235, 237, 238, 243, 245, 246, 249, 250, 252, 127, 191, 223, 239, 247, 251, 253, 254, 255}

const idx[9][2] = {{0, 0}, {1, 8}, {9, 36}, {37, 92}, {93, 162}, {163, 218}, {219, 246}, {247, 254}, {255, 255}};

series[random(idx[n][0], idx[n][1])]

даст случайное число с n единицами

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...