|
Как рациональнее всего преобразовать float в int? |
|
|
|
Dec 21 2010, 12:33
|
Гуру
     
Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164

|
Господа, есть небольшая задачка. Работаю с дисплеем и тачскрином. Как вы сами понимаете, координаты дисплея и координаты тачскрина - это две большие разницы (или, как говорят в Одессе, четыре маленьких)) ).
координаты дислпея вычисляются следующим образом: х=touch_x*800/256 y=touch_y*480/256
Но полученный результат является float, а функция, куда будут переданы координаты берет int. Естественно, такой вариант как скажем Circle (touch_x*800/256, touch_y*480/256 .....) не прокатит.
Мне хочется с наименьшими процессорными затратами получить округленные числа типа int, как это сделать? Ибо способов существует несколько, а вот какой быстрее....
Спасибо.
Сообщение отредактировал zheka - Dec 21 2010, 12:34
|
|
|
|
|
Dec 21 2010, 12:44
|
Участник

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

|
Если touch_x и touch_y типа int, то и результат будет типа int. Все операции умножения и деления будут выполнятся с целыми числами. И в принципе на округление можно забить, так как палец на тачскрине всё округлит сам.
|
|
|
|
|
Dec 21 2010, 13:04
|
Гуру
     
Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164

|
rezident, сейчас переварю, то что Вы написали, а пока для сравнения, вот что у меня было: Код _X=(float)*touch_x*800/256; _Y=(float)*touch_y*480/256; FillEllipse(800-(int)(_X),(int)(_Y),10,10,clRed); Это затратнее чем Ваш вариант? Проверил. Мой вышеприведенный вариант позволял рисовать на экране стилусом. Ваш вариант в моем использовании: FillEllipse(800-((*touch_x*800)>>8),((*touch_y*480)>>8),10,10,clRed); рисует в правом верхнем углу экрана, в квадрате со стороной 256х256 пикселей. У тачпанель 0,0 находятся в правом верхнем углу экрана. touch_x у меня типа unsigned char
Сообщение отредактировал zheka - Dec 21 2010, 13:07
|
|
|
|
|
Dec 21 2010, 13:11
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
Вы, надеюсь, понимаете, что координаты вашего устройства отображения это сугубо целые числа? Так на кой вам float? Некуда процессорное время девать? Да и написали бы лучше: Код х=((*touch_x)*800)>>8; y=((*touch_y)*480)>>8; FillEllipse(800-x, y, 10, 10, clRed);
|
|
|
|
|
Dec 21 2010, 13:29
|
Гуру
     
Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164

|
Цитата Вы, надеюсь, понимаете, что координаты вашего устройства отображения это сугубо целые числа? Подозревать человека, который в состоянии собрать отладочную плату и подключить с ней дисплей глупо. В свою очередь, я надеюсь что вы понимаете что произойдет если unsigned char умножить на 800. Итог - мой вариант работает, но безусловно тратит процессорное время. Ваш вариант работает как и предложенный резидентом.
Сообщение отредактировал zheka - Dec 21 2010, 13:33
|
|
|
|
|
Dec 21 2010, 13:42
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
zheka, а вы дроби из курса начальной школы не забыли еще? Например, запись 0,125 означает 125/1000. И числитель и знаменатель дроби являются целыми числами. Цитата(zheka @ Dec 21 2010, 21:29)  В свою очередь, я надеюсь что вы понимаете что произойдет если unsigned char умножить на 800. В соответствии со стандартом Си произойдет конвертация в тип signed integer, в котором эти числа и будут перемножены. Однако если переменные x и y у вас тоже типа char, то результат умножения будет преобразован к типу char. Вывод: вычислять нужно, приведя операнды к типу long.
|
|
|
|
|
Dec 21 2010, 13:49
|
Гуру
     
Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164

|
Да нет же, я не о целых и дробях, я о том, что touch_x не может быть равен больше 255, если прибавить к 245 число 20, получится не 265, а 10. У пишущих здесь есть возможность проверить это в компиляторе? В моем варианте я оперирую с float, а затем по окончании привожу float к int, не только потому что я, как ни странно знаю, что координаты это целое число, а еще и потому, что функция не возьмет float. Цитата В соответствии со стандартом Си произойдет конвертация в тип signed integer, в котором эти числа и будут перемножены. ОДнако на практике - в Вашем варианте, пока я веду стилусом вдоль х, курсор на экране 4 раза пробегает от координаты 544 к координате 800. Значит все таки не происходит конвертации. Цитата Вывод: вычислять нужно, приведя операнды к типу long. То есть то же самое, что у меня, только приводя к long, так? СРазу вопрос работа с long менее затратна, чем с float ? Поверьте, мне нужно не просто чтобы работало, а чтобы работало быстро настолько, насколько это возможно силами C.
|
|
|
|
|
Dec 21 2010, 14:00
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
Цитата(zheka @ Dec 21 2010, 20:29)  Подозревать человека, который в состоянии собрать отладочную плату и подключить с ней дисплей глупо.
В свою очередь, я надеюсь что вы понимаете что произойдет если unsigned char умножить на 800.
Итог - мой вариант работает, но безусловно тратит процессорное время. Ваш вариант работает как и предложенный резидентом. Ну вы же нам исходя, видимо, из соображений секретности, даже не сказали, что за процессор/компилятор пользуете. Как вы там объявили свои х, тouch_x - тайна, покрытая мраком. У вас int, часом, не 16-бит? Так почему надо упорно лезть во float, а не применить, действительно, что-нибудь типа long (хотя это тоже загадка, что этот long на вашем процессоре из себя представляет)? Ну да, вы же в разделе AVR. int он и есть 16-бит. Сделайте так: Код х=(((long int)touch_x)*800L)>>8; y=(((long int)touch_y)*480L)>>8; FillEllipse(800-x, y, 10, 10, clRed);
|
|
|
|
|
Dec 21 2010, 15:53
|
Гуру
     
Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164

|
У меня CodeVision 2, процессор - atmega32 Сейчас попробую то что вы написали. Объявлял так Код unsigned char x; unsigned char y; unsigned char *touch_x; unsigned char *touch_y;
int sX; int sY;
.....
void main ()
.....
touch_x = &x; touch_y = &y; Получаю координаты функцией GetTouchStat(touch_x,touch_y); То что вы предложили - не работает.
|
|
|
|
|
Dec 21 2010, 16:23
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
Цитата(zheka @ Dec 21 2010, 22:53)  У меня CodeVision 2, процессор - atmega32 Сейчас попробую то что вы написали. Объявлял так Код unsigned char x; unsigned char y; unsigned char *touch_x; unsigned char *touch_y;
int sX; int sY;
.....
void main ()
.....
touch_x = &x; touch_y = &y; Получаю координаты функцией GetTouchStat(touch_x,touch_y); То что вы предложили - не работает. Делаем так: Код unsigned char x; unsigned char y;
int sX; int sY;
.....
void main ()
.....
GetTouchStat(&x, &y);
sX=(int)((((long int)x)*800L)>>8); sY=(int)((((long int)y)*480L)>>8); FillEllipse(800-sX, sY, 10, 10, clRed); Кстати. Touchscreen выдает координаты в диапазоне 0...255 или более того?
|
|
|
|
|
Dec 21 2010, 16:28
|
Гуру
     
Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164

|
Код sX=(int)((((long int)x)*800L)>>8); sY=(int)((((long int)y)*480L)>>8); FillEllipse(800-sX, sY, 10, 10, clRed); Вот это другое дело! Работает, так как надо. И, судя по тому, что рисуемые на большой скорости передвижения стилуса точки получаются гуще - работает быстрее. Спасибо! Цитата Touchscreen выдает координаты в диапазоне 0...255 или более того? 0-255. Иначе зачем я делил на 256?
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|