|
Математика в AvrStudio, Проблемы с программированием вычислений |
|
|
|
May 13 2009, 15:56
|
Частый гость
 
Группа: Участник
Сообщений: 126
Регистрация: 7-08-07
Пользователь №: 29 631

|
Здравствуйте. Помогите, пожалуйста, советом, в каком месте описано как правильно организовывать переменные и проводить вычисления в Atmeg-ах. Пишу программку для , в которой нужно проводить множество математических операций (в основном умножений, делений, сложений). Чо-то очень туго у меня получается. Компилятор выдает вовсе не то что прошу. Не могу уловить систему моих ошибок  . Я раньше с IARом работал - там как-то проще было (правда и вычислений в тех задачах особых не было).
|
|
|
|
|
 |
Ответов
|
May 16 2009, 19:21
|
Частый гость
 
Группа: Участник
Сообщений: 126
Регистрация: 7-08-07
Пользователь №: 29 631

|
Хотя я методом тыка раздуплил проблемку, которая подвигнула меня на оформление данной темы, на будущее очень хочется услышать комментарии спецов  . С Вашего позволения привожу код примера моих проблем. Итак некоторая функция должна рассчитывать пилу по заданному углу. Сперва я написал все формулы влоб: Код 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;} Вроде по разрядной сетке противоречий нет. Но ничего не получилось  Далее я крутил крутил и интуитивно получил рабочий вариант: Код 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;} Как же правильно решать подобные задачки ?
|
|
|
|
|
May 17 2009, 14:53
|
Частый гость
 
Группа: Свой
Сообщений: 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.
|
|
|
|
|
May 17 2009, 15:16
|

Гуру
     
Группа: Модераторы
Сообщений: 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)
|
|
|
|
|
May 17 2009, 15:42
|
Частый гость
 
Группа: Свой
Сообщений: 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бит?
|
|
|
|
|
May 17 2009, 16:11
|

Гуру
     
Группа: Модераторы
Сообщений: 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)
|
|
|
|
Сообщений в этой теме
Aiva Математика в AvrStudio May 13 2009, 15:56 defunct Цитата(Aiva @ May 13 2009, 18:56) Я раньш... May 13 2009, 18:22 IXFN50N80Q2 Хм. Ну ANSI C а вообще для начала отключите опимиз... May 13 2009, 18:57 Сергей Борщ Цитата(Aiva @ May 13 2009, 18:56) Компиля... May 13 2009, 20:41 777777 Цитата(IXFN50N80Q2 @ May 13 2009, 22:57) ... May 15 2009, 09:04 SysRq Цитата(Aiva @ May 16 2009, 23:21) Как же ... May 16 2009, 21:13     _Diman_ Спасибо!
Блин, я то думал что так тоже прави... May 17 2009, 16:26 DpInRock Цитатаif ((angle>90)&(angle<=270))
Чисто... May 16 2009, 20:29 777777 Цитата(DpInRock @ May 17 2009, 00:29) Цит... May 17 2009, 04:21  Aiva Цитата(777777 @ May 17 2009, 07:21) А что... May 17 2009, 06:14 DpInRock В данном случае работать должно и &. May 16 2009, 21:21
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|