|
|
  |
Округление при сдвиговом делении, возможно, детский вопрос, но все же... |
|
|
|
Nov 20 2007, 16:26
|
Знающий
   
Группа: Свой
Сообщений: 518
Регистрация: 12-04-07
Из: Санкт-Петербург
Пользователь №: 26 997

|
Итак, есть число, знаковое. Его надо разделить Вариант 1: на степень двойки. Сдвигаем вправо и все. Округление, на сколько я знаю, до ближайшего целого в сторону минус бесконечности. Вариант 2: не на степень двойки, а, скажем, на 1.6. Деление на 1.6 выполняем следующим образом: 1/1.6 = 0.625 = (1/2+1/8). Т.е. сдвигаем на один бит и прибавляем результат сдвига на 3 бита. Какое округление происходит в данном случае я даже не знаю.
А теперь вопрос: как выполнить деление по первому и второму варианту, но гарантировать округление до ближайшего целого (и для положительных, и для отрицательных)? Причем, в проекте это одно из самых узких мест, не хотелось бы накручивать сложную логику и плодить задержки. Заранее спасибо
|
|
|
|
|
Nov 21 2007, 06:12
|
Знающий
   
Группа: Свой
Сообщений: 518
Регистрация: 12-04-07
Из: Санкт-Петербург
Пользователь №: 26 997

|
Цитата(rloc @ Nov 20 2007, 19:36)  В самом простом случае добавляете к числу +0.5 и для положительных и для отрицательных чисел, и откидываете дробную часть. Хм. Осталось только придумать, как это реализовать. Цитата(Гвоздик @ Nov 21 2007, 00:47)  Вы дробную арифметику самостоятельно в целочисленную приводите?!? Матлабом пользоваться не пробовали? Советую попробовать связку программ: AccelDSP + Matlab (HDL-код напишется автоматически) А что мне предлагается делать на матлабе? Мне нужно выполнить квантование на набор заранее рассчитанных коефициентов, округляя результат к ближайшему целому. Что мне тут сделать на матлабе и чем он мне поможет? Я сегодня проверю, но, на сколько помню, функции округления в матлабе - не hdl синтезируемые.
|
|
|
|
|
Nov 21 2007, 08:23
|
Знающий
   
Группа: Свой
Сообщений: 518
Регистрация: 12-04-07
Из: Санкт-Петербург
Пользователь №: 26 997

|
Цитата(Волощенко @ Nov 21 2007, 09:45)  Похоже, Вы масштабируете на заранее известные коэффициенты: попробуйте заменить деление умножением. Или условия другие? Ну да, есть входной поток d0, d1, d2,..., d63. Есть набор значений, заранее известных и доступных небольшому варьированию q0, q1, q2,..., q63. На выходе нужно d0/q0, d1/q1, d2/q2, ..., d63/q34 с округлением к ближайшему целому. Можно пример замены деления умножением?
|
|
|
|
|
Nov 21 2007, 15:05
|
Знающий
   
Группа: Свой
Сообщений: 518
Регистрация: 12-04-07
Из: Санкт-Петербург
Пользователь №: 26 997

|
Цитата(Волощенко @ Nov 21 2007, 11:48)  Если у Вас есть свободный умножитель в ПЛИС, .... тогда лучше объяснить все на примерах: Об этом и подумал, но решил уточнить. Спасибо. Если не удастся придумать другой вариант, то так и буду делать, но изначально хотелось все сделать на сдвигах. Хотя, пока писал - в уме прикинул, на умножителе получится удобнее в плане написания самого кода. Пожалуй, так и сделаю, а уж если по ТТХ не пройдет, тогда буду изворачиваться. Всем большое спасибо за помощь!
|
|
|
|
|
Nov 23 2007, 10:47
|
Участник

Группа: Новичок
Сообщений: 20
Регистрация: 13-10-06
Пользователь №: 21 281

|
Цитата(RHnd @ Nov 20 2007, 20:26)  Итак, есть число, знаковое. Его надо разделить Вариант 1: на степень двойки. Сдвигаем вправо и все. Округление, на сколько я знаю, до ближайшего целого в сторону минус бесконечности. Вариант 2: не на степень двойки, а, скажем, на 1.6. Деление на 1.6 выполняем следующим образом: 1/1.6 = 0.625 = (1/2+1/8). Т.е. сдвигаем на один бит и прибавляем результат сдвига на 3 бита. Какое округление происходит в данном случае я даже не знаю. Думаю, все будет гораздо наглядней и понятней, если изменить последовательность операций. Вариант 1. (А >> n) + 0.5 == (A+2**(n-1)) >> n Вариант 2. A/2 + A/8 + 0.5 == (A >> 1) + (A >> 3) + 0.5 == ((A << 2) + A + (0.5 << 3)) >> 3 == ((A << 2) + A + (1 << 2)) >> 3 Иными словами: вначале прибавить 2**(n-1), а затем смело отбросить n разраядов.
|
|
|
|
|
Dec 11 2007, 14:52
|

Частый гость
 
Группа: Свой
Сообщений: 129
Регистрация: 28-11-06
Пользователь №: 22 854

|
Цитата(AsJohnAs @ Nov 21 2007, 16:00)  Тут правельно сказано что надо добавлять 0,5. Реализация подобного может быть сделана примерно так: число 010101000 надо круглить отбросив 3 младших бита. Для этого надо к 010101000 добавить 000000100. Абсолютно с Вами согласен, а что если 011111111 надо округлить отбросив 3 младших бита?При добавлении 000000100 не произойдет ли переполнение?
--------------------
Противник, вскрывающий ваши ошибки, гораздо полезнее, чем друг, скрывающий их. /Леонардо да Винчи/
|
|
|
|
|
Dec 12 2007, 06:39
|
Участник

Группа: Свой
Сообщений: 52
Регистрация: 13-11-07
Пользователь №: 32 296

|
Цитата(AsJohnAs @ Nov 21 2007, 15:00)  Тут правельно сказано что надо добавлять 0,5. Реализация подобного может быть сделана примерно так: число 010101000 надо круглить отбросив 3 младших бита. Для этого надо к 010101000 добавить 000000100. Петрушка какая то получается, пример вы приводите некорректный. Вы округляете 010101000 до целого числа, представляя младшие 3 бита как дробную часть. Округляют обычно так - если дробная часть >= 0.5 к целой части добавляют 1, иначе берут просто целую часть. В Вашем примере дробная часть (первые три бита) уже и так равна нулю, так что прибавлять единицу не надо. Прибавляют обычно росто бинарный разряд, стоящий на одну позицию меньше чем остающиеся разряды. В таком случае прибавление 1 происходит автоматически если дробная не меньше 0.5
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|