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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Как рациональнее всего преобразовать float в int?
zheka
сообщение Dec 21 2010, 12:33
Сообщение #1


Гуру
******

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Dec 21 2010, 12:40
Сообщение #2


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



QUOTE (zheka @ Dec 21 2010, 19:33) *
Но полученный результат является float, а функция, куда будут переданы координаты берет int.

Кто сказал? Если int x,y; то результат будет int sm.gif
Go to the top of the page
 
+Quote Post
fantex
сообщение Dec 21 2010, 12:44
Сообщение #3


Участник
*

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



Если touch_x и touch_y типа int, то и результат будет типа int. Все операции умножения и деления будут выполнятся с целыми числами. И в принципе на округление можно забить, так как палец на тачскрине всё округлит сам.
Go to the top of the page
 
+Quote Post
rezident
сообщение Dec 21 2010, 12:45
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Зачем вам float вообще? Вычисляйте в целых числах. Ведь сами координаты-то точек являются целыми числами.
х=(touch_x*800)>>8;
y=(touch_y*480)>>8;
Если уж так непременно нужны дробные результаты, то и представляйте их в виде дроби с основанием двойки.
Go to the top of the page
 
+Quote Post
zheka
сообщение Dec 21 2010, 13:04
Сообщение #5


Гуру
******

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Dec 21 2010, 13:11
Сообщение #6


Профессионал
*****

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



Вы, надеюсь, понимаете, что координаты вашего устройства отображения это сугубо целые числа? Так на кой вам float? Некуда процессорное время девать?

Да и написали бы лучше:

Код
х=((*touch_x)*800)>>8;
y=((*touch_y)*480)>>8;
FillEllipse(800-x, y, 10, 10, clRed);
Go to the top of the page
 
+Quote Post
zheka
сообщение Dec 21 2010, 13:29
Сообщение #7


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Цитата
Вы, надеюсь, понимаете, что координаты вашего устройства отображения это сугубо целые числа?


Подозревать человека, который в состоянии собрать отладочную плату и подключить с ней дисплей глупо.


В свою очередь, я надеюсь что вы понимаете что произойдет если unsigned char умножить на 800.

Итог - мой вариант работает, но безусловно тратит процессорное время. Ваш вариант работает как и предложенный резидентом.

Сообщение отредактировал zheka - Dec 21 2010, 13:33
Go to the top of the page
 
+Quote Post
rezident
сообщение Dec 21 2010, 13:42
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 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.
Go to the top of the page
 
+Quote Post
zheka
сообщение Dec 21 2010, 13:49
Сообщение #9


Гуру
******

Группа: Участник
Сообщений: 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.
Go to the top of the page
 
+Quote Post
rezident
сообщение Dec 21 2010, 13:50
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(zheka @ Dec 21 2010, 21:48) *
ОДнако на практике - в Вашем варианте, пока я веду стилусом вдоль х, курсор на экране 4 раза пробегает от координаты 544 к координате 800. Значит все таки не происходит конвертации.
Нет смысла обсуждать видимые результаты, если неизвестны причины, порождающие их. Я имею в виду типы переменных и функции, которые вы применяете. Нам о них ничего не известно.
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Dec 21 2010, 14:00
Сообщение #11


Профессионал
*****

Группа: Свой
Сообщений: 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);
Go to the top of the page
 
+Quote Post
zheka
сообщение Dec 21 2010, 15:53
Сообщение #12


Гуру
******

Группа: Участник
Сообщений: 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);

То что вы предложили - не работает.
Go to the top of the page
 
+Quote Post
777777
сообщение Dec 21 2010, 16:13
Сообщение #13


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(zheka @ Dec 21 2010, 21:53) *
То что вы предложили - не работает.

Код
unsigned char x;
unsigned char y;

int sX;
int sY;

.....

void main ()

.....

GetTouchStat(&x,&y);
sX = x;
sY = Y;

А так работает? С sX, sY выполняешь вычисления. По моим прикидкам 16-разрядного ште должно хватить sm.gif

Сообщение отредактировал 777777 - Dec 21 2010, 16:13
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Dec 21 2010, 16:23
Сообщение #14


Профессионал
*****

Группа: Свой
Сообщений: 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 или более того?
Go to the top of the page
 
+Quote Post
zheka
сообщение Dec 21 2010, 16:28
Сообщение #15


Гуру
******

Группа: Участник
Сообщений: 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?
Go to the top of the page
 
+Quote Post

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

 


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


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