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

|
Здравствуйте. Помогите, пожалуйста, советом, в каком месте описано как правильно организовывать переменные и проводить вычисления в Atmeg-ах. Пишу программку для , в которой нужно проводить множество математических операций (в основном умножений, делений, сложений). Чо-то очень туго у меня получается. Компилятор выдает вовсе не то что прошу. Не могу уловить систему моих ошибок  . Я раньше с IARом работал - там как-то проще было (правда и вычислений в тех задачах особых не было).
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 14)
|
May 13 2009, 20:41
|

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

|
Цитата(Aiva @ May 13 2009, 18:56)  Компилятор выдает вовсе не то что прошу. Не могу уловить систему моих ошибок  . Я раньше с 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)
|
|
|
|
|
May 15 2009, 09:04
|

Профессионал
    
Группа: Участник
Сообщений: 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 не так поймет и подумает что эти строчки кода лишние. Если он так подумает - значит они и в самом деле лишние.
|
|
|
|
|
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 16 2009, 20:29
|

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

Профессионал
    
Группа: Участник
Сообщений: 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) { ... } А что, эта функция вычисляет синус?
|
|
|
|
|
May 17 2009, 06:14
|
Частый гость
 
Группа: Участник
Сообщений: 126
Регистрация: 7-08-07
Пользователь №: 29 631

|
Цитата(777777 @ May 17 2009, 07:21)  А что, эта функция вычисляет синус? Я ее просто так назвал. Она вычисляет пилу, похожую на синус.
|
|
|
|
|
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)
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|