Страница 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... умножаем... округляем... ну вот так всё ровно же? Сначала?
:shock:
Зачем все это?
:))) :))) :)))
Округление нужно ОДНО и для этого нужно сначала получить ВДВОЕ бОльший результат, а затем проанализировать МЛАДШИЙ разряд. Если он =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 бывает разная....
И "бОльшая наглядность" в КОНКРЕТНОМ случае не имеет никакого смысла.
:wink:
Как и байтный формат выходных чисел....
:roll: :wink: