|
|
  |
Операции над большими числами, Операции над большими числами |
|
|
|
Mar 9 2010, 21:25
|
Частый гость
 
Группа: Участник
Сообщений: 84
Регистрация: 21-10-09
Пользователь №: 53 117

|
Цитата(=GM= @ Mar 9 2010, 23:29)  Правильно так: (5050/10^8)*2^28 =0x13BA0000000/0x5F5E100=0x34F4=13556 А я вот тут подумал, а если подойти к задаче с дугой стороны. Я посмотрел, что прибавление или вычитание из кода идет с шагом или 2 или 3. Закономерность вроде как тоже есть.. Изменение на 2 происходит после двух подряд изменений на три и так пять раз, после чего три раза подряд изменение на три и цикл снова.. 2333 233 233 233 233 233 23332...... Может быть по такому пути проще идти и не городить огород со сложной математикой.. Только как бы это привязать к какому либо значению?? Или придется тупо на каких то хитрых циклах делать??
Сообщение отредактировал NickSmith - Mar 9 2010, 21:26
|
|
|
|
|
Mar 9 2010, 21:33
|
Частый гость
 
Группа: Участник
Сообщений: 84
Регистрация: 21-10-09
Пользователь №: 53 117

|
Цитата(rx3apf @ Mar 10 2010, 00:31)  Фигней не надо заниматься, а ? Всего-то нужно тривиальное деление 40 / 20 битов. Простейший цикл сдвиг-сравнение-вычитание. А по подробней можно??
|
|
|
|
|
Mar 9 2010, 23:03
|
Частый гость
 
Группа: Участник
Сообщений: 84
Регистрация: 21-10-09
Пользователь №: 53 117

|
Цитата(rx3apf @ Mar 10 2010, 01:55)  Ну как делается деление "столбиком" ? Так и здесь - сдвигаем делимое в накопитель остатка, сравниваем остаток с делимым, если больше либо равен - вычитаем делимое из остатка и записываем "1" в результат. Иначе не вычитаем и записываем "0". Для удобства регистр делителя и результата совмещается, по окончанию операции частное будет в том же накопителе. Реализации под конкретную платформу - практически всегда есть в аппликухах... Т.е делать все по формуле.. Хорошо, а как быт с округлением результатов? у меня же ведь на выходе получается число с запятой.. А в демо программе, как я понял результат расчетов округляется или в большую или в меньшую сторону? Как поделить и умножить я разберусь, а вот как быть с остатком.. Я делаю это на tiny2313 там есть пример математики с большими числами.. Но он очень громоздок.. Что то строк под 150 по моему.. По этому я и подумал пойти простым путем и поиграть с увеличением или уменьшением готовой константы.. Кода по моему всяко меньше получится??
|
|
|
|
|
Mar 10 2010, 07:44
|
Гуру
     
Группа: Участник
Сообщений: 3 834
Регистрация: 14-06-06
Из: Moscow, Russia
Пользователь №: 18 047

|
Цитата(NickSmith @ Mar 10 2010, 02:03)  Т.е делать все по формуле.. Хорошо, а как быт с округлением результатов? у меня же ведь на выходе получается число с запятой.. А в демо программе, как я понял результат расчетов округляется или в большую или в меньшую сторону? Как поделить и умножить я разберусь, а вот как быть с остатком.. Я уже говорил, как это сделать проще. Делимое взять вдвое больше, а после деления частное еще раз поделить вдвое простым сдвигом и по состоянию бита переноса добавить единичку к результату. Цитата Я делаю это на tiny2313 там есть пример математики с большими числами.. Но он очень громоздок.. Что то строк под 150 по моему.. Жуть какая... Вот деление 32 / 16. Добавить по одному регистру в делимое, частное и остаток, будет требуемые 40 / 24... CODE ;---------------------------------------------------------------------- ; Деление XH:XL:YH:YL / ZH:ZL ; Используются регистры r0, r1, temp ;----------------------------------------------------------------------
Div32: clr r0 clr r1 ldi temp,32 ; счетчик Div32_1: lsl YL rol YH rol XL rol XH ; сдвиг делимого rol r1 rol r0 ; и остатка (r0:r1) cp r1,ZL cpc r0,ZH ; можно вычесть делитель ? brlo Div32_2 ; нет ori YL,$01 ; иначе "1" в частное sub r1,ZL sbc r0,ZH Div32_2: dec temp brne Div32_1 ; цикл деления
; В XH:XL:YH:YL содержится результат деления
ret
|
|
|
|
|
Mar 10 2010, 10:48
|
Частый гость
 
Группа: Участник
Сообщений: 84
Регистрация: 21-10-09
Пользователь №: 53 117

|
Цитата(rx3apf @ Mar 10 2010, 10:44)  Я уже говорил, как это сделать проще. Делимое взять вдвое больше, а после деления частное еще раз поделить вдвое простым сдвигом и по состоянию бита переноса добавить единичку к результату.
Жуть какая... Вот деление 32 / 16. Добавить по одному регистру в делимое, частное и остаток, будет требуемые 40 / 24... Огромное спасибо за пример.. Но я все равно под запутался. Выше писали: Цитата Правильно так: (5050/10^8)*2^28 =0x13BA 0000 000/0x5F5E100=0x34F4=13556 Но получается не 0x34F4, 0x34F3 Вот если взять делимое на 1 ноль больше, то результат будет 0x34f3f Если младшую тетраду младшего байта как то обрабатывать по условию, то и получится округление.. Прав??
|
|
|
|
|
Mar 10 2010, 10:56
|
Гуру
     
Группа: Участник
Сообщений: 3 834
Регистрация: 14-06-06
Из: Moscow, Russia
Пользователь №: 18 047

|
Цитата(NickSmith @ Mar 10 2010, 13:48)  Но получается не 0x34F4, 0x34F3 Вот если взять делимое на 1 ноль больше, то результат будет 0x34f3f Если младшую тетраду младшего байта как то обрабатывать по условию, то и получится округление.. Прав?? Мать-перемать... Ну сколько можно объяснять ? Надо взять делимое вдвое больше (умножить на 2^29), а потом частное поделить еще на 2 сдвигом вправо, и по состоянию переноса прибавить или не прибавляь 1 (т.е. для avr сделать adc. Для приведенной мной программы - lsr xh ror xl ror yh ror yl adc yl,temp adc yh,temp adc xl,temp adc xh temp). Конеччно, это можно сделать и контролем остатка, но так - проще. Естественно, в примере с конкретными числами разрядность можно сократить на 8 битов, поэтому достаточно деление 40 / 24.
Сообщение отредактировал rx3apf - Mar 10 2010, 10:57
|
|
|
|
|
Mar 10 2010, 11:01
|
Частый гость
 
Группа: Участник
Сообщений: 84
Регистрация: 21-10-09
Пользователь №: 53 117

|
Цитата(rx3apf @ Mar 10 2010, 13:56)  Мать-перемать... Ну сколько можно объяснять ? Надо взять делимое вдвое больше (умножить на 2^29), а потом частное поделить еще на 2 сдвигом вправо, и по состоянию переноса прибавить или не прибавляь 1 (т.е. для avr сделать adc. Для приведенной мной программы - lsr xh ror xl ror yh ror yl adc yl,temp adc yh,temp adc xl,temp adc xh temp). Конеччно, это можно сделать и контролем остатка, но так - проще. Естественно, в примере с конкретными числами разрядность можно сократить на 8 битов, поэтому достаточно деление 40 / 24. Все, теперь понял ход вашей мысли..
|
|
|
|
|
Mar 10 2010, 15:14
|
Участник
  
Группа: Свой
Сообщений: 462
Регистрация: 2-04-07
Из: Иркутск
Пользователь №: 26 695

|
Цитата(NickSmith @ Mar 10 2010, 19:01)  Все, теперь понял ход вашей мысли.. Если я правильно понял, нужно вычислять выражение вида a*b/c, где a - частота, которую нужно получить, b - разрядность 28 bit, c - частота кварца. Причём, b и c - константы. вычисляем b/c = 2^28/10^8 = 2.68435456. Получается, нужно только одно умножение a*k, где k=2.68435456. проверяем для 5050*k=13555.990528. Так как плавающая точка всё равно не нужна и в синтезатор загружаем целые числа, то вместо k надо взять N=k<<16 или k<<24 или сколько там нужно разрядов для этого синтезатора, и работаем только с целочисленным умножением. Пример для 16-bit результата: N=k*2^16=0x2AF32, 5050*N=0x34F40054, старшие два байта и есть искомое 0x34F4
|
|
|
|
|
Mar 10 2010, 17:12
|
Частый гость
 
Группа: Участник
Сообщений: 84
Регистрация: 21-10-09
Пользователь №: 53 117

|
Цитата(ae_ @ Mar 10 2010, 18:14)  Если я правильно понял, нужно вычислять выражение вида a*b/c, где a - частота, которую нужно получить, b - разрядность 28 bit, c - частота кварца. Причём, b и c - константы. вычисляем b/c = 2^28/10^8 = 2.68435456. Получается, нужно только одно умножение a*k, где k=2.68435456. проверяем для 5050*k=13555.990528. Так как плавающая точка всё равно не нужна и в синтезатор загружаем целые числа, то вместо k надо взять N=k<<16 или k<<24 или сколько там нужно разрядов для этого синтезатора, и работаем только с целочисленным умножением. Пример для 16-bit результата: N=k*2^16=0x2AF32, 5050*N=0x34F40054, старшие два байта и есть искомое 0x34F4 Изящный способ, но у него с округлением проблемы... А у меня это критично.. Хотя так конечно было бы проще..
|
|
|
|
|
Mar 10 2010, 17:27
|
Участник
  
Группа: Свой
Сообщений: 462
Регистрация: 2-04-07
Из: Иркутск
Пользователь №: 26 695

|
Цитата(NickSmith @ Mar 11 2010, 01:12)  Изящный способ, но у него с округлением проблемы... А у меня это критично.. Хотя так конечно было бы проще.. С округлением всё просто, стрший бит отбрасываемой части прибавляем к результату, и всё.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|