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

 
 
> Умножение дробных чисел
golovin
сообщение May 29 2007, 05:39
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 37
Регистрация: 13-04-07
Пользователь №: 27 012



Добрый день!

Необходимо разделить число на 5, т.е. умножить на 0,2. Но я не могу получить ровно 0,2 при переводе числа в дробное по методу ATMEL (Appl. Note 201).

Погрешность которая получается не устраивает, т.к. числа, которые необходимо делить на 5 находятся в диапазоне 1..100, соответственно набегает ошибка около 35.

Есть ли какой-то выход из этой ситуации ?

Спасибо
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 24)
mse
сообщение May 29 2007, 06:10
Сообщение #2


Знающий
****

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



Цитата(golovin @ May 29 2007, 09:39) *
Есть ли какой-то выход из этой ситуации ?

Не знаю, что там в апноте, но попробуй умножать на 1/5. Т.е. на 256/5 или 65536/5 или...смотря какая точность нужна. Ну и, ессно, один, два...млачшеньких бутеса долой. А то и не долой, мало ли?
Go to the top of the page
 
+Quote Post
Диm
сообщение May 29 2007, 06:15
Сообщение #3


Участник
*

Группа: Новичок
Сообщений: 24
Регистрация: 31-05-06
Пользователь №: 17 614



Цитата(golovin @ May 29 2007, 11:39) *
Добрый день!

Необходимо разделить число на 5, т.е. умножить на 0,2. Но я не могу получить ровно 0,2 при переводе числа в дробное по методу ATMEL (Appl. Note 201).

Погрешность которая получается не устраивает, т.к. числа, которые необходимо делить на 5 находятся в диапазоне 1..100, соответственно набегает ошибка около 35.

Есть ли какой-то выход из этой ситуации ?

Спасибо

лично я бы сделал так, делимое умножал 100,а делитель оставлял как есть(5),а полученный результат был в формате z*10-2(99*100/5=1980*0,01). для работы с большими числами пользовался маленькой библиотечкой,точнее копи-пастил нужные куски (там написано сложение,вычитание,деление,умножение 32битных чисел,перевод BCD2bin и Bin2BCD всё на ассемблере)
Прикрепленные файлы
Прикрепленный файл  mathoperation.rar ( 12.11 килобайт ) Кол-во скачиваний: 83
 
Go to the top of the page
 
+Quote Post
golovin
сообщение May 29 2007, 06:18
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 37
Регистрация: 13-04-07
Пользователь №: 27 012



В App.Note как раз описана технология перевода дробных чисел в формат, который используют мк. Если коротко, то старший бит 7 = 2^0 =1, следующий 6 = 2^-1 = 0.5 ... 0 = 2^-7 = 0.0078125, таким образом записав соответствующие 1 и 0 в нужные биты получам дробное число, которое используется в команде FMUL или FMULS. Например, 0.75 = 01100000.
Go to the top of the page
 
+Quote Post
mse
сообщение May 29 2007, 06:20
Сообщение #5


Знающий
****

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



Цитата(Диm @ May 29 2007, 10:15) *
лично я бы сделал так, делимое умножал 100,а делитель оставлял как есть(5),а полученный результат был в формате z*10-2(99*100/5=1980*0,01). для работы с большими числами пользовался маленькой библиотечкой,точнее копи-пастил нужные куски (там написано сложение,вычитание,деление,умножение 32битных чисел,перевод BCD2bin и Bin2BCD всё на ассемблере)

Не надо делитель ;О) Деление в 8-15 раз(зависит от писателя) медленнее умножения. Длиннее, больше жрёт ресурсов...Ацтой, короче.
Go to the top of the page
 
+Quote Post
Диm
сообщение May 29 2007, 06:25
Сообщение #6


Участник
*

Группа: Новичок
Сообщений: 24
Регистрация: 31-05-06
Пользователь №: 17 614



Цитата(mse @ May 29 2007, 12:20) *
Не надо делитель ;О) Деление в 8-15 раз(зависит от писателя) медленнее умножения. Длиннее, больше жрёт ресурсов...Ацтой, короче.

не спорю!может тут надо считать десять раз в секунду,не более этого.тогда это самое простое помоемуsmile.gif
Go to the top of the page
 
+Quote Post
golovin
сообщение May 29 2007, 07:43
Сообщение #7


Участник
*

Группа: Участник
Сообщений: 37
Регистрация: 13-04-07
Пользователь №: 27 012



К сожалению программное умножение/деление не подходит из-за медлительности.
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение May 29 2007, 07:50
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(golovin @ May 29 2007, 10:43) *
К сожалению программное умножение/деление не подходит из-за медлительности.

Еще сдвиг существует. Сдвинули влево - поделили - сдвинули вправо (или оставили так, отбросив лишнее при выводе или последующих вычислениях ).
И вообще, зачем делить то? Приведите к величине, чтобы точность устраивала.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
mse
сообщение May 29 2007, 08:00
Сообщение #9


Знающий
****

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



Цитата(golovin @ May 29 2007, 11:43) *
К сожалению программное умножение/деление не подходит из-за медлительности.

Правда? ;О) Озвучте лимит времени. 16Х16 любая мега оттарабанит за 16 тактов. А вам нужно не больше 16Х8.
Go to the top of the page
 
+Quote Post
ae_
сообщение May 29 2007, 08:04
Сообщение #10


Участник
***

Группа: Свой
Сообщений: 462
Регистрация: 2-04-07
Из: Иркутск
Пользователь №: 26 695



Цитата(golovin @ May 29 2007, 16:43) *
К сожалению программное умножение/деление не подходит из-за медлительности.

Умножение выполняется всего за 2 такта, о какой медлительности идёт речь?
Код
LDI DELIMOE, 100
LDI DELITEL, 256/5
MUL DELIMOE, DELITEL

В регистре R1 будет результат 100/5=20
Go to the top of the page
 
+Quote Post
golovin
сообщение May 29 2007, 08:06
Сообщение #11


Участник
*

Группа: Участник
Сообщений: 37
Регистрация: 13-04-07
Пользователь №: 27 012



Т.е. любая мега сможет поделить на 5 или умножить на 0,2 программно за 16 тактов ?
Не подскажите, где можно найти такой код ? И точность не подскажите?

Цитата(ae_ @ May 29 2007, 12:04) *
Умножение выполняется всего за 2 такта, о какой медлительности идёт речь?
Код
LDI DELIMOE, 100
LDI DELITEL, 256/5
MUL DELIMOE, DELITEL

В регистре R1 будет результат 100/5=20


Я вроде писал о ПРОГРАММНОМ умножении, а не АППАРАТНОМ

А приведённый код даст следующее :

Delitel = $33 = 51

Результат : R1 = $13, R2 = $EC

Сообщение отредактировал golovin - May 29 2007, 08:11
Go to the top of the page
 
+Quote Post
mse
сообщение May 29 2007, 08:18
Сообщение #12


Знающий
****

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



Цитата(golovin @ May 29 2007, 12:06) *
Т.е. любая мега сможет поделить на 5 или умножить на 0,2 программно за 16 тактов ?
Не подскажите, где можно найти такой код ? И точность не подскажите?

Да. берём число N и умножаем на 0х34(256/5+1) или на 0х3334(65536/5+1). От результата помножения берём старший байт.
Думаю, если не надо иметь десятые, то 0х34 будет достаточно.
Есть такой пласт знаний:AVR200.asm, AVR200b.asm, AVR201.asm. Находится в Аппнотах АСМа Астудии.
Цитата
Я вроде писал о ПРОГРАММНОМ умножении, а не АППАРАТНОМ

Щас только тиньки обделены умножителем. Ну, на худой конец, рукопашный умножитель 16Х8 будет тактов 60-70. 8х8 тама 34 такта рукопашных.
Go to the top of the page
 
+Quote Post
ae_
сообщение May 29 2007, 08:21
Сообщение #13


Участник
***

Группа: Свой
Сообщений: 462
Регистрация: 2-04-07
Из: Иркутск
Пользователь №: 26 695



Цитата(golovin @ May 29 2007, 17:06) *
Т.е. любая мега сможет поделить на 5 или умножить на 0,2 программно за 16 тактов ?
Не подскажите, где можно найти такой код ? И точность не подскажите?
Я вроде писал о ПРОГРАММНОМ умножении, а не АППАРАТНОМ

А приведённый код даст следующее :

Delitel = $33 = 51

Результат : R1 = $13, R2 = $EC

Результат R1=19 (целая часть), R0(не R2)=236/256=0,921875 - дробная часть. Точность равна единице млашего разряда =1/256 при условии, что делитель точный. У вас делитель =51 вместо 51.2, так что точность будет меньше. Если такая точность не устраивает, в формате 8.8, используйте 8.16. В этом случае надо умножать делимое на 65336/5, результат будет 3-х байтный, старший байт - целая часть, два младших - дробная.
Go to the top of the page
 
+Quote Post
mse
сообщение May 29 2007, 08:25
Сообщение #14


Знающий
****

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



Цитата(ae_ @ May 29 2007, 12:21) *
Результат R1=19 (целая часть), R0(не R2)=236/256=0,921875 - дробная часть. Точность равна единице млашего разряда =1/256 при условии, что делитель точный. У вас делитель =51 вместо 51.2, так что точность будет меньше. Если такая точность не устраивает, в формате 8.8, используйте 8.16. В этом случае надо умножать делимое на 65336/5, результат будет 3-х байтный, старший байт - целая часть, два младших - дробная.

Будет то-же самое, только вид сбоку. ;О) надо множить на 256/5+1. На худой конец, к старшему дробному байту мона прибавлять 0х80, а к результату, с переносом, 0х0. Но это фигня лишняя.
Go to the top of the page
 
+Quote Post
golovin
сообщение May 29 2007, 08:31
Сообщение #15


Участник
*

Группа: Участник
Сообщений: 37
Регистрация: 13-04-07
Пользователь №: 27 012



to mse: по поводу программного и аппаратного это я не Вам

По поводу App.Note'ов - читал.
По поводу R2 - опечатался.

В том то и дело, что нужно определить числа кратные 5. А такой метод не даёт точности. Т. е. если R0 = 0 - кратное. А так приходится вводить некую дельту и плясать вокруг неё. А это время.
Go to the top of the page
 
+Quote Post
mse
сообщение May 29 2007, 08:43
Сообщение #16


Знающий
****

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



Цитата(golovin @ May 29 2007, 12:31) *
В том то и дело, что нужно определить числа кратные 5. А такой метод не даёт точности. Т. е. если R0 = 0 - кратное. А так приходится вводить некую дельту и плясать вокруг неё. А это время.

Никакой проблемы ;О) вам нужна дробная часть. Множите число на 0х3334 и смотрите средний байт, если "0", то таво...
Go to the top of the page
 
+Quote Post
golovin
сообщение May 29 2007, 08:50
Сообщение #17


Участник
*

Группа: Участник
Сообщений: 37
Регистрация: 13-04-07
Пользователь №: 27 012



А можно поподробней про число 0х3334 ?
Go to the top of the page
 
+Quote Post
mse
сообщение May 29 2007, 08:56
Сообщение #18


Знающий
****

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



Цитата(golovin @ May 29 2007, 12:50) *
А можно поподробней про число 0х3334 ?

Дык, этта...65536/5+1
Go to the top of the page
 
+Quote Post
golovin
сообщение May 29 2007, 09:44
Сообщение #19


Участник
*

Группа: Участник
Сообщений: 37
Регистрация: 13-04-07
Пользователь №: 27 012



to mse: БОЛЬШОЕ спасибо
Go to the top of the page
 
+Quote Post
ae_
сообщение May 29 2007, 10:31
Сообщение #20


Участник
***

Группа: Свой
Сообщений: 462
Регистрация: 2-04-07
Из: Иркутск
Пользователь №: 26 695



Цитата(mse @ May 29 2007, 17:43) *
Никакой проблемы ;О) вам нужна дробная часть. Множите число на 0х3334 и смотрите средний байт, если "0", то таво...

У меня получилось обойтись одним умножением 8х8
Код
    ldi    R16, 99    ;Число для проверки на кратность 5-ти, 0...255
    ldi    R17, 256/5;Множитель = 1/5 * 256
    mul    R16, R17;Умножаем(делим :)
    ldi    R17, 205;У всех чисел, кратных 5-ти, дробная часть >=205
    cp    R0, R17    ;Сравниваем дробную часть с пороговым значением
    brsh    KRATNO_5;Переход, если число кратно 5-ти
    tst    R16    ;Проверка делимого на ноль
    breq    KRATNO_5;Делимое=0, тоже кратно 5-ти
NE_KRATNO_5:
;...
KRATNO_5:
;...

Для golovin - если не требуется считать 0 кратным 5-ти, то пару строк можно убрать:
tst R16 ;Проверка делимого на ноль
breq KRATNO_5 ;Делимое=0, тоже кратно 5-ти
Go to the top of the page
 
+Quote Post
mse
сообщение May 29 2007, 10:46
Сообщение #21


Знающий
****

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



Цитата(ae_ @ May 29 2007, 14:31) *
У меня получилось обойтись одним умножением 8х8

Вполне мобуть!
Go to the top of the page
 
+Quote Post
defunct
сообщение May 29 2007, 15:55
Сообщение #22


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Есть такой интересный алгоритм деления на 10:

Для 8-ми битных чисел:

Y = (X * 0xCD) >> 11;

Для 16-ти битных

Y = ( X * 0xCCCD) >> 19;

Для 32-х битных

Y = ( X * 0xCCCCCCCD) >> 35

Если сдвинете на бит меньше - получите деление на 5.
Go to the top of the page
 
+Quote Post
m16
сообщение May 30 2007, 08:56
Сообщение #23


Местный
***

Группа: Свой
Сообщений: 242
Регистрация: 27-01-05
Пользователь №: 2 225



Цитата(defunct @ May 29 2007, 19:55) *
Есть такой интересный алгоритм деления на 10:

добавлю по теме полезный ресурс http://www.cs.uiowa.edu/~jones/bcd/divide.html
Go to the top of the page
 
+Quote Post
golovin
сообщение May 30 2007, 11:07
Сообщение #24


Участник
*

Группа: Участник
Сообщений: 37
Регистрация: 13-04-07
Пользователь №: 27 012



Спасибо за интересные мысли !
Go to the top of the page
 
+Quote Post
umup
сообщение Jun 1 2007, 02:17
Сообщение #25


Местный
***

Группа: Свой
Сообщений: 226
Регистрация: 2-06-06
Пользователь №: 17 720



Вот, может подойдет - для 8 и 16 битных чисел. Первый вариант функции для контроллеров без умножителя, второй - с умножителем.

Код
/** \brief unsigned 8-bit division by 5 (using shifts)<br>деление беззнакового 8-битного числа на 5 (если нет аппаратного умножения) \ingroup group_math */
u8 div_by5_u8_soft(u8 data_in)
{u16 u16_01, result;
result = u16_01 = data_in;
u16_01 <<= 1; result += u16_01;
u16_01 <<= 3; result += u16_01;
u16_01 <<= 1; result += u16_01;
result += 0x33; //correction
return(result >> 8);
}

/** \brief unsigned 8-bit division by 5 (using multiply)<br>деление беззнакового 8-битного числа на 5 (если есть аппаратное умножение) \ingroup group_math */
u8 div_by5_u8_hmul(u8 data_in)
{return((((u16)data_in * 0x33) + 0x33) >> 8);
}

/** \brief unsigned 16-bit division by 5 (using shifts)<br>деление беззнакового 16-битного числа на 5 (если нет аппаратного умножения) \ingroup group_math */
u16 div_by5_u16_soft(u16 data_in)
{u32 u32_01, result;
result = u32_01 = data_in;
u32_01 <<= 1; result += u32_01;
u32_01 <<= 3; result += u32_01;
u32_01 <<= 1; result += u32_01;
u32_01 <<= 3; result += u32_01;
u32_01 <<= 1; result += u32_01;
u32_01 <<= 3; result += u32_01;
u32_01 <<= 1; result += u32_01;
result += 0x3333; //correction
return(result >> 16);
}

/** \brief unsigned 16-bit division by 5 (using multiply)<br>деление беззнакового 16-битного числа на 5 (если есть аппаратное умножение) \ingroup group_math */
u16 div_by5_u16_hmul(u16 data_in)
{return((((u32)data_in * 0x3333) + 0x3333) >> 16);
}
Go to the top of the page
 
+Quote Post

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

 


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


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