Страница 1 из 2
отбросить дробную часть
Добавлено: Чт янв 09, 2014 15:39:10
-==MAXCELERON==-
Приветствую уважаемые)) Давненько не программил и позабыл(( Вобщем проблема в следующем: есть функция delay(), которой необходимо передавать целое число ms, но это число получаем путем умножения числа X на 1.2, в результате получается дробное значение, как его конвертировать то в целое, всю голову сломал уже на такой мелочи ((
Код: Выделить всё
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <util/delay.h>
#define F_CPU 8000000UL
volatile int x=1;
void delay(int ms){
for(;ms;ms--)
_delay_ms(1);
}
int main(void){ //Главная функция
while (1) {
PORTB = 0X01;
delay(x);
x=x*1.2;
PORTB = 0X00;
}
}
Re: отбросить дробную часть
Добавлено: Чт янв 09, 2014 15:56:00
zöner
попробуйте x = ((u32)x * 307) >> 8
Re: отбросить дробную часть
Добавлено: Чт янв 09, 2014 16:09:15
-==MAXCELERON==-
неа, ошибка( кстати программлю в винавре)
Re: отбросить дробную часть
Добавлено: Чт янв 09, 2014 16:20:31
zöner
по-вашему что должно получиться если int 1 умножить на 1.2 ?
Re: отбросить дробную часть
Добавлено: Чт янв 09, 2014 16:37:39
-==MAXCELERON==-
1 это так для красоты написал , на самом деле 90 Задача в том, чтобы с каждым циклом задержка увеличивалась в 1,2 раза))
Re: отбросить дробную часть
Добавлено: Чт янв 09, 2014 16:48:57
zöner
Re: отбросить дробную часть
Добавлено: Чт янв 09, 2014 17:36:55
-==MAXCELERON==-
error: 'u32' undeclared (first use in this function)
Re: отбросить дробную часть
Добавлено: Чт янв 09, 2014 17:55:32
zöner
x = (x * 307uL) >> 8
Re: отбросить дробную часть
Добавлено: Чт янв 09, 2014 17:57:27
GARMIN
zöner писал(а):(u32)x
Как вы думаете, что автор имел ввиду в этом выражении?
Подсказывать, не значит решать за вас. Читайте раздел "типы данных".
Re: отбросить дробную часть
Добавлено: Чт янв 09, 2014 18:13:49
-==MAXCELERON==-
zöner писал(а):x = (x * 307uL) >> 8
Спасибо)) работает) а что за uL??
Re: отбросить дробную часть
Добавлено: Чт янв 09, 2014 18:22:57
zöner
Re: отбросить дробную часть
Добавлено: Чт янв 09, 2014 19:21:45
-==MAXCELERON==-
Ага понятно)) а каков алгоритм получения числа 307?? методом тыка?
Re: отбросить дробную часть
Добавлено: Чт янв 09, 2014 19:34:18
zöner
x * 1.2 = x * 1.2 * 256 / 256 ~= x * 307 >> 8
Re: отбросить дробную часть
Добавлено: Чт янв 09, 2014 19:37:08
-==MAXCELERON==-
Математика проста)) Спасибо за помощь)) пополню копилку знаний)
Re: отбросить дробную часть
Добавлено: Чт янв 09, 2014 19:48:33
-==MAXCELERON==-
Господин zöner, прошу прощения за назойливость, а как быть, если требуется наоборот - делить?
Re: отбросить дробную часть
Добавлено: Чт янв 09, 2014 19:56:43
-==MAXCELERON==-
Все разобрался сам)) 256/1.2 = 212
Re: отбросить дробную часть
Добавлено: Пн янв 13, 2014 07:03:51
nirq
чтобы с каждым циклом задержка увеличивалась в 1,2 раза
Если в начале задержка всегда одинаковая (и состоит из восьми бит) - составляем таблицу:
1
1 * 1.2 = 1.2 = 1
1.2 * 1.2 = 1.44 = 1
1.44 * 1.2 = 1.728 =
1 (если тупо отбросили дробную часть) или 2
(если заморочились с округлением)
...
итого не более чем 256 значений в таблице.
Экономим память? А время не экономим? А округляем в какую сторону?
Делёжка, синусоида, x = x^2 * tg(sqrt(x)) + 14/5...
Если нужна
реальная арифметика, а не таблица, потому что нужна РЕАЛЬНАЯ В НАТУРЕ арифметика, а не таблица:
начинаем с единицы, умножаем на 1.2, округляем, получаем единицу, опять умножаем её на 1.2...
ой нет ну конечно единица была для красоты, а на самом деле начальное значение будет равно 90... умножаем... округляем... ну вот так всё ровно же? Сначала?
Re: отбросить дробную часть
Добавлено: Пн янв 13, 2014 09:02:52
КРАМ
nirq писал(а):
Если нужна реальная арифметика, а не таблица, потому что нужна РЕАЛЬНАЯ В НАТУРЕ арифметика, а не таблица:
начинаем с единицы, умножаем на 1.2, округляем, получаем единицу, опять умножаем её на 1.2...
ой нет ну конечно единица была для красоты, а на самом деле начальное значение будет равно 90... умножаем... округляем... ну вот так всё ровно же? Сначала?
Зачем все это?
Округление нужно ОДНО и для этого нужно сначала получить ВДВОЕ бОльший результат, а затем проанализировать МЛАДШИЙ разряд. Если он =1 (это дробная часть результата = 0,5), то после еще одного сдвига нужно прибавить единицу, а если в этом разряде 0, то после сдвига ничего прибавлять не нужно.
На АСМе это выглядит компактнее.
Достаточно анализа бита переноса ПОСЛЕ получения результата (после сдвига через перенос).
nirq писал(а):
Экономим память? А время не экономим?
Никакой практической экономии времени с таблицей не будет.
Адресация таблицы даст примерно такой же расход времени, и к тому же точность однозначно будет ограничена 1 байтом.
Re: отбросить дробную часть
Добавлено: Пн янв 13, 2014 11:48:07
nirq
Опять и снова соглашаемся, что х таки да: состоит из 8 бит (хотя это и не принципиально).
Я не знаю, что обозначает int на языке примера в начале, поэтому на всякий случай обозначил явно размер.
Для большей наглядности берём микросхему (восьмибитную и) без аппаратного умножения - например AVR.
Для ещё большей наглядности считаем по формуле более сложной, чем просто "умножить на К либо на 1/К". В общем виде.
Код: Выделить всё
ldi ZH, high(Table * 2) ; таблица выровнена по 256-байтным границам, старший байт адреса не меняется
ldi ZL, low(Table * 2)
ldi counter, MaxCounter
next:
lpm temp, Z
; do something with temp - желательно не такое пошлое, как / существенно более интеллектуальное, чем "прокрутиться temp раз в пустом цикле"
; ... или кому и зачем надо это всё
inc ZL
;brne pc + 2 - не надо
;inc ZH
dec counter
brne next
Возвращаемся к формуле "x = x * 1.2", но начинаем с какого-нибудь другого значения - например, с 94 (в общем, опять же, виде).
Без промежуточных округлений в заранее подготовленной таблице было бы:
94 112.8=113 135.36=
135 162.432=
162 ...
С промежуточными округлениями (до 8 бит) "на лету" получалось бы:
94 113
136 163 ...
Даже если искомый конь так и не перестал быть сугубо сферическим - смысл-то не в коне, а в победе над оппонентом! Восемнадцать кульных смайлов.
Re: отбросить дробную часть
Добавлено: Пн янв 13, 2014 12:06:29
КРАМ
nirq писал(а):
Для большей наглядности берём микросхему (восьмибитную и) без аппаратного умножения - например AVR.
AVR бывает разная....
И "бОльшая наглядность" в КОНКРЕТНОМ случае не имеет никакого смысла.
Как и байтный формат выходных чисел....
