реклама на сайте
подробности

 
 
4 страниц V  < 1 2 3 4 >  
Reply to this topicStart new topic
> Простой ГСП на Си
Herz
сообщение Jan 18 2014, 10:55
Сообщение #16


Гуру
******

Группа: Модераторы
Сообщений: 10 983
Регистрация: 23-11-05
Пользователь №: 11 287



Странно, но вот у меня такая функция:

Код
unsigned char rnd8(unsigned char max)
{
static unsigned int seed = 0;
unsigned char temp, i;
unsigned int    sub;

seed = (seed << 7) - seed + 251;
temp =  (unsigned char)(seed + (seed>>8));
i = 8; sub = max << 8;

do     {
      sub >>= 1;
      if (sub >= temp) temp -= sub;
    } while (--i);

return temp;
}

(минимум опустил пока для простоты)

при вызове:
Код
NUM = rnd8(MAX);

где
Код
#define        MAX        30


работает неверно. Диапазон не соблюдает. Более того, старший бит всегда 1.
Go to the top of the page
 
+Quote Post
SM
сообщение Jan 18 2014, 11:07
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881



Я допустил описку, сорри... Писал прямо в форум...

if (sub >= temp) должно быть наоборот, if (temp >= sub)
Go to the top of the page
 
+Quote Post
Herz
сообщение Jan 18 2014, 11:13
Сообщение #18


Гуру
******

Группа: Модераторы
Сообщений: 10 983
Регистрация: 23-11-05
Пользователь №: 11 287



Семён Семёныч! biggrin.gif
Да, теперь работает отлично. Ещё раз большое спасибо.
Кстати, temp не приводится к типу sub при temp -= sub; ?
Go to the top of the page
 
+Quote Post
SM
сообщение Jan 18 2014, 11:16
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881



Цитата(Herz @ Jan 18 2014, 15:13) *
Кстати, temp не приводится к типу sub при temp -= sub; ?

По ANSI это не требуется, компилятор сам приведет к нужному типу, а я не любитель писать лишние сущности, потенциально полезные только для наглядности.
Go to the top of the page
 
+Quote Post
Herz
сообщение Jan 18 2014, 11:22
Сообщение #20


Гуру
******

Группа: Модераторы
Сообщений: 10 983
Регистрация: 23-11-05
Пользователь №: 11 287



Цитата(SM @ Jan 18 2014, 13:16) *
По ANSI это не требуется, компилятор сам приведет к нужному типу, а я не любитель писать лишние сущности, потенциально полезные только для наглядности.

Нет, я имею в виду, не возвращает ли функция int в этом случае вместо char после приведения? Или типом функции это задаётся строго?
Go to the top of the page
 
+Quote Post
SM
сообщение Jan 18 2014, 11:30
Сообщение #21


Гуру
******

Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881



Цитата(Herz @ Jan 18 2014, 15:22) *
Нет, я имею в виду, не возвращает ли функция int в этом случае вместо char после приведения? Или типом функции это задаётся строго?


В контексте Вашего вопроса, приведения в "temp -= sub", это задается типом переменной temp, при присваивании в 8-битную переменную автоматически все лишнее обрезается, и оптимизатор, по идее, должен сам определить это, и использовать 8-битные операции для всего выражения (которое по ANSI должно было считаться в 16 битах, а потом обрезаться).

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

UPD:
PS
по логике, кстати, в том выражении надо не temp приводить к типу sub, а наоборот, учитывая, что по условию там temp >= sub, что означает, что реальная разрядность числа в sub меньше либо равна 8. Т.е. для наглядности и для подсказки оптимизатору можно написать temp -= (u8) sub;
Go to the top of the page
 
+Quote Post
Herz
сообщение Jan 18 2014, 11:40
Сообщение #22


Гуру
******

Группа: Модераторы
Сообщений: 10 983
Регистрация: 23-11-05
Пользователь №: 11 287



ОК, я понял. То есть и у TSerg смысла в явном приведении в строке:

Код
return (u8)(seed + (seed>>8));


не было?
Go to the top of the page
 
+Quote Post
SM
сообщение Jan 18 2014, 11:42
Сообщение #23


Гуру
******

Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881



Цитата(Herz @ Jan 18 2014, 15:40) *
То есть и у TSerg смысла в явном приведении в строке:


Да. Только наглядность. Ну и, возможно, уничтожение warning-а компилятора о том, что теряется разрядность, если этот warning включен по умолчанию.
Go to the top of the page
 
+Quote Post
Fat Robot
сообщение Jan 18 2014, 14:15
Сообщение #24


ʕʘ̅͜ʘ̅ʔ
*****

Группа: Свой
Сообщений: 1 008
Регистрация: 3-05-05
Пользователь №: 4 691



Не нужно вам никакого деления и остатка от деления.

1. делаете генератор в полном диапазоне int16 или int8. с помощью LFSR. Вам написали.

2. рассматриваете выход генератора как fractional число Q1.15, если выход int16, или Q1.7, если выход int8. Таким образом у вас есть RNG с fractional выходом в диапазоне [-1; 1)

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

можно обнулять старший бит и тогда на выходе RNG получать [0; 1). Дальнейшая арифметика в этом случае видится немного попроще.
Будет, правда, слегка перекошенное распределение (для ненулевого числа x != 0 будет вероятность выпадения p(x); если же x = 0, то p(0) ~= 1.5*p(x) ), но для мигалки это не принципиально, мне кажется.

Итого: сдвиги, суммы, одно умножение
Go to the top of the page
 
+Quote Post
SM
сообщение Jan 18 2014, 20:42
Сообщение #25


Гуру
******

Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881



Цитата(Fat Robot @ Jan 18 2014, 18:15) *
одно умножение


так вот в нем и зло. если нету ни аппаратного умножителя, ни аппаратного делителя, то и на умножение получим цикл на 8 итераций, и на нахождение остатка от деления тоже 8 итераций. При этом умножение, скорее, проиграет на 8-битном RNG и 8-битном процессоре по причине 16-битного суммирования в цикле против 8-битного вычитания, но выиграет - очень врядли (хотя, конечно, этот вопрос надо отдельно изучить, что оптимальнее на конкретной архитектуре). И при этом нахождение остатка не испортит распределение.

Ну а если аппаратное умножение имеется, то тут, разумеется, совсем другой расклад по производительности. Но вроде в обычном PIC его и нету...
Go to the top of the page
 
+Quote Post
Victor®
сообщение Jan 18 2014, 21:12
Сообщение #26


Lazy
******

Группа: Свой
Сообщений: 2 070
Регистрация: 21-06-04
Из: Ukraine
Пользователь №: 76



Цитата(Herz @ Jan 17 2014, 23:13) *
Предположим, требуется моргать светодиодом с псевдослучайным интервалом от 2 до 30 секунд.
Посоветуйте простую функцию на Си для генерации целых чисел в таком малом диапазоне. Пусть от 1 до 255 максимум.
Функция rand() из библиотеки HT-PICC тяжеловата как-то...


Что-то все все усложняют...
На светодиод наверное человек смотреть будет?
Так вот через несколько он забудет, что видел при этом моргании.
Просто сделайте таблицу на пару минут и все...

Или игровой автомат? Тогда запись на видео лишит всего дохода... sm.gif

П.С.
Или Вам надо офигенно нормальное распределение?
Увы - ничего не выйдет....


--------------------
"Everything should be made as simple as possible, but not simpler." - Albert Einstein
Go to the top of the page
 
+Quote Post
Herz
сообщение Jan 18 2014, 22:16
Сообщение #27


Гуру
******

Группа: Модераторы
Сообщений: 10 983
Регистрация: 23-11-05
Пользователь №: 11 287



Цитата(Fat Robot @ Jan 18 2014, 16:15) *
Не нужно вам никакого деления и остатка от деления.

Сразили! Я и слов-то таких не знаю: fractional. biggrin.gif Буде Ваша воля пояснить свою идею попроще, постараюсь разобраться...

Цитата(SM @ Jan 18 2014, 22:42) *
Ну а если аппаратное умножение имеется, то тут, разумеется, совсем другой расклад по производительности. Но вроде в обычном PIC его и нету...

На данном этапе имеется PIC18, в котором аппаратное умножение присутствует. Но хочется перенести проект на PIC16, где на эту задачу желательно потратить минимум ресурсов.

Цитата(Victor® @ Jan 18 2014, 23:12) *
Что-то все все усложняют...
На светодиод наверное человек смотреть будет?
Так вот через несколько он забудет, что видел при этом моргании.
Просто сделайте таблицу на пару минут и все...

Или игровой автомат? Тогда запись на видео лишит всего дохода... sm.gif

П.С.
Или Вам надо офигенно нормальное распределение?
Увы - ничего не выйдет....

Да нет, светодиод - это пример, упрощение. На самом деле нужно посылать некий сигнал, но нерегулярно. Чтобы не привыкнуть. Таблица отпадает - памяти маловато. Хотя...
Но, от добра добра не ищут: пример от ув. SM очень даже ничего.
Go to the top of the page
 
+Quote Post
Fat Robot
сообщение Jan 18 2014, 23:55
Сообщение #28


ʕʘ̅͜ʘ̅ʔ
*****

Группа: Свой
Сообщений: 1 008
Регистрация: 3-05-05
Пользователь №: 4 691



Объясню предельно просто, не жонглируя терминологией

Пусть генератор после всех преобразований имеет выход X в диапазоне [0; (2^n)-1]
нужно и можно найти такие постоянные значения Y и Z, чтобы значение числа round((X*Y) >> Z) лежало в диапазоне [0; max-min]

Все, что для этого нужно это (((max-min) * X ) + (1 << (n - 1))) >> n.

Пусть n=7, a max-min=27
X в диапазоне [0; 127]
((X*27)+64)>>7 будет лежать в диапазоне [0;27]
выход операции умножения 16 бит

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

пусть вместо 27 из примера вас устроит 24 = (2^4) + (2^3), тогда преобразование будет таким:
(( X << 4 ) + ( X << 3 ) + 64 )>>7 и выход будет лежать в диапазоне [0;24]


Цитата(Herz @ Jan 18 2014, 23:16) *
Буде Ваша воля пояснить свою идею попроще, постараюсь разобраться...
Go to the top of the page
 
+Quote Post
Herz
сообщение Jan 19 2014, 06:58
Сообщение #29


Гуру
******

Группа: Модераторы
Сообщений: 10 983
Регистрация: 23-11-05
Пользователь №: 11 287



Благодарю Вас, теперь ясно.
Go to the top of the page
 
+Quote Post
Tanya
сообщение Jan 19 2014, 08:05
Сообщение #30


Гуру
******

Группа: Модераторы
Сообщений: 8 752
Регистрация: 6-01-06
Пользователь №: 12 883



Цитата(Fat Robot @ Jan 19 2014, 03:55) *
то нужно выбрать такое значение,
чтобы в нем было как можно меньше единиц в двоичных разрядах,

? На, к примеру, 31 тоже ведь легко умножить.
Go to the top of the page
 
+Quote Post

4 страниц V  < 1 2 3 4 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 5th July 2025 - 18:05
Рейтинг@Mail.ru


Страница сгенерированна за 0.01521 секунд с 7
ELECTRONIX ©2004-2016