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

 
 
> Математика в AvrStudio, Проблемы с программированием вычислений
Aiva
сообщение May 13 2009, 15:56
Сообщение #1


Частый гость
**

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



Здравствуйте.
Помогите, пожалуйста, советом, в каком месте описано как правильно организовывать переменные и проводить вычисления в Atmeg-ах.

Пишу программку для , в которой нужно проводить множество математических операций (в основном умножений, делений, сложений). Чо-то очень туго у меня получается. Компилятор выдает вовсе не то что прошу. Не могу уловить систему моих ошибок sad.gif.
Я раньше с IARом работал - там как-то проще было (правда и вычислений в тех задачах особых не было).
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 14)
defunct
сообщение May 13 2009, 18:22
Сообщение #2


кекс
******

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



Цитата(Aiva @ May 13 2009, 18:56) *
Я раньше с IARом работал - там как-то проще было (правда и вычислений в тех задачах особых не было).

Так работайте дальше с IAR'ом. В чем вопрос?
Go to the top of the page
 
+Quote Post
IXFN50N80Q2
сообщение May 13 2009, 18:57
Сообщение #3


Частый гость
**

Группа: Свой
Сообщений: 138
Регистрация: 12-05-09
Пользователь №: 48 987



Хм. Ну ANSI C а вообще для начала отключите опимизатор. Уровень O0.
Бывает что и сам WIN AVR GCC не так поймет и подумает что эти строчки кода лишние.
И самое главное в скобках, там где переменная после умножения выше unsigned char становится, то надо ставить в скобках тип контейнера.
А лучше всегда его прописывать.

unsigned char X,Y;
unsigned int Result

Result=(unsigned int)X*Y ----->Перемножение 2х CHARов пораждает тип INT. И нужно указать, что считать X-16разрядным числом. Это я имел ввиду под типом контейнера.
Вот так.

Если Result=X*Y
хоть и Result ИНТ, могут быть проблемы.

А остальное это документуха по ANSI C.
А вообще смотрите Дизассемблер. Говорят помогает.

Сообщение отредактировал IXFN50N80Q2 - May 13 2009, 19:00
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 13 2009, 20:41
Сообщение #4


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Aiva @ May 13 2009, 18:56) *
Компилятор выдает вовсе не то что прошу. Не могу уловить систему моих ошибок sad.gif.
Я раньше с IARом работал - там как-то проще было (правда и вычислений в тех задачах особых не было).
Будьте добры, задавайте вопросы конкретнее: что вы пишете, что ожидаете получить и что получаете. Было бы совсем замечательно, если бы вы подкрепили конкретным примером - что именно было в IAR проще. Пока по предоставленной вами информации можно лищь ответить: "пишите правильно".
Цитата(IXFN50N80Q2 @ May 13 2009, 21:57) *
Хм. Ну ANSI C а вообще для начала отключите опимизатор. Уровень O0.
Очень вредный совет. Пользы никакой, только размер кода увеличится и скорость вычислений упадет.
Цитата(IXFN50N80Q2 @ May 13 2009, 21:57) *
Бывает что и сам WIN AVR GCC не так поймет и подумает что эти строчки кода лишние.
Вот только не надо валить все с больной головы на компилятор. Компилятор делает то, что попросили. Если попросили некоррекно - виноват не компилятор.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
777777
сообщение May 15 2009, 09:04
Сообщение #5


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

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



Цитата(IXFN50N80Q2 @ May 13 2009, 22:57) *
Хм. Ну ANSI C а вообще для начала отключите опимизатор. Уровень O0.

Глупости. Этот режим сделан для того, чтобы люди, думающие, что виноват оптимизатор, могли его отключить и убедиться, что на самом деле ошибка в их программе.
Цитата(IXFN50N80Q2 @ May 13 2009, 22:57) *
Бывает что и сам WIN AVR GCC не так поймет и подумает что эти строчки кода лишние.

Если он так подумает - значит они и в самом деле лишние.
Go to the top of the page
 
+Quote Post
Aiva
сообщение May 16 2009, 19:21
Сообщение #6


Частый гость
**

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



Хотя я методом тыка раздуплил проблемку, которая подвигнула меня на оформление данной темы, на будущее очень хочется услышать комментарии спецов smile.gif. С Вашего позволения привожу код примера моих проблем.

Итак некоторая функция должна рассчитывать пилу по заданному углу. Сперва я написал все формулы влоб:

Код
const unsigned int N0=0b10000000000000;
const unsigned int Nmax=0b11111111111111;
unsigned long  Wvariable2;

unsigned long sinus(unsigned int angle)
{
  if (angle<=90)
   { Wvariable2=N0+angle*Nmax/180;}
  if (angle>270)
   { Wvariable2 = (angle-270)*Nmax/180;}
  if ((angle>90)&(angle<=270))
   { Wvariable2 = Nmax-(angle-90)*Nmax/180;}
return Wvariable2;}


Вроде по разрядной сетке противоречий нет. Но ничего не получилось sad.gif
Далее я крутил крутил и интуитивно получил рабочий вариант:

Код
unsigned int sinus(unsigned int angle)
{
unsigned long  Wvariable2;
unsigned int Wv1;

      Wvariable2 = Nmax;
  if (angle<=90)
    {
      Wvariable2 *= angle;
      Wvariable2 = Wvariable2/180;
      Wvariable2 += N0;
      Wv1=Wvariable2;    
    }
  if (angle>270)
    {
      Wvariable2 *= (angle-270);
      Wv1= (Wvariable2/180);
    }
  if ((angle>90)&(angle<=270))
    {
      Wvariable2 *= (angle-90);
      Wvariable2 = Wvariable2/180;
      Wv1 = (Nmax-Wvariable2);
    }
return Wv1;}


Как же правильно решать подобные задачки ?
Go to the top of the page
 
+Quote Post
DpInRock
сообщение May 16 2009, 20:29
Сообщение #7


Гуру
******

Группа: Участник
Сообщений: 2 254
Регистрация: 4-05-07
Из: Moscow
Пользователь №: 27 515



Цитата
if ((angle>90)&(angle<=270))

Чисто тут лучше && ставить. Полезнее на будущее. И быстрее.

Во-вторых (тут уже говорили) учитывать, что тип результата всегда равен типу операндов(или самого длинного), если специально не указать иное.
Вот в первом случае angle*Nmax приводит временами к переполнению промежуточного результата.

Сообщение отредактировал DpInRock - May 16 2009, 20:32


--------------------
On the road again (Canned Heat)
Go to the top of the page
 
+Quote Post
SysRq
сообщение May 16 2009, 21:13
Сообщение #8


Чайник, 1 литр
****

Группа: Свой
Сообщений: 655
Регистрация: 17-05-06
Из: Moscow
Пользователь №: 17 168



Цитата(Aiva @ May 16 2009, 23:21) *
Как же правильно решать подобные задачки ?
Взять любимую книжку-учебник по языку C, прочесть об приведении типов, автоматическом приведении типов, и уверенно решать.

& и && - вообще разные вещи. Результат (1 & 2) и (1 && 2) вообще-то противоположный...

Сообщение отредактировал SysRq - May 16 2009, 21:13
Go to the top of the page
 
+Quote Post
DpInRock
сообщение May 16 2009, 21:21
Сообщение #9


Гуру
******

Группа: Участник
Сообщений: 2 254
Регистрация: 4-05-07
Из: Moscow
Пользователь №: 27 515



В данном случае работать должно и &.


--------------------
On the road again (Canned Heat)
Go to the top of the page
 
+Quote Post
777777
сообщение May 17 2009, 04:21
Сообщение #10


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

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



Цитата(DpInRock @ May 17 2009, 00:29) *
Цитата
if ((angle>90)&(angle<=270))

Чисто тут лучше && ставить. Полезнее на будущее. И быстрее.

И к тому же можно обойтись без лишних скобок. В Си приоритеты выбраны так, чтобы можно было в большинстве случаев обойтись без скобок.


Цитата(Aiva @ May 16 2009, 23:21) *
Код
unsigned long sinus(unsigned int angle)
{
...
}

А что, эта функция вычисляет синус?
Go to the top of the page
 
+Quote Post
Aiva
сообщение May 17 2009, 06:14
Сообщение #11


Частый гость
**

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



Цитата(777777 @ May 17 2009, 07:21) *
А что, эта функция вычисляет синус?


Я ее просто так назвал. Она вычисляет пилу, похожую на синус.
Go to the top of the page
 
+Quote Post
_Diman_
сообщение May 17 2009, 14:53
Сообщение #12


Частый гость
**

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



Цитата(Aiva @ May 16 2009, 23:21) *
Код
   { Wvariable2=N0+angle*Nmax/180;}
//------------------
{
      Wvariable2 *= angle;
      Wvariable2 = Wvariable2/180;
      Wvariable2 += N0;
      Wv1=Wvariable2;    
    }


Интересно, а так работать будет?
Код
   { Wvariable2=N0+(angle*Nmax)/180UL;}

Я так понял не работает из-за того, что выражение считается для int.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 17 2009, 15:16
Сообщение #13


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(_Diman_ @ May 17 2009, 17:53) *
Интересно, а так работать будет?
Код
   { Wvariable2=N0+(angle*Nmax)/180UL;}
Тоже не будет. А вот Wvariable2=N0+ angle * (unsigned long)Nmax/180 будет.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
_Diman_
сообщение May 17 2009, 15:42
Сообщение #14


Частый гость
**

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



Цитата(Сергей Борщ @ May 17 2009, 19:16) *
Тоже не будет. А вот Wvariable2=N0+ angle * (unsigned long)Nmax/180 будет.


Объясните, пожалуйста, если не трудно, почему так.
Умножение и деление имеют один приоритет и в строке выполняются слева на право
почему, например, (unsigned long)angle * Nmax/180 будет не верно, по идее то angle уже 32битная. Я почему-то думал, что проблем с переменными при операциях не возникнет, возникнут, когда действия будут с константой и переменной. А тут получается, что angle*Nmax не расширяется до 32бит?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 17 2009, 16:11
Сообщение #15


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(_Diman_ @ May 17 2009, 18:42) *
Объясните, пожалуйста, если не трудно, почему так.
Правила вычисления подвыражений. Тип результата определеяется типом наибольшего операнда. Второй операнд приводится к этому же типу. Если оба операнда меньше int, они приводятся к int (integer promotion rules). Оптимизатор имеет право потом убрать действия, которые не влияют на конечный результат.
Разбиваем ваше выражение на подвыражения: angle * Nmax - оба операнда unsigned int, результат unsigned int. В процессе вычисления происходит переполнение. Для исключения ошибки надо один из операндов привести к unsigned long. Любой, не обязательно именно Nmax. А вот приведение 180 ничего не дает, потому что в подвыражении деления первый операнд - уже обрезанный до unsigned int результат умножения. И именно этот усеченный результат будет расширен до 32 бит.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post

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

 


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


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