Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Не считает функция log().
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
-Игорь-
Споткнулся на ровном месте. Надо подсчитывать натуральный логарифм. Иcпользую функцию log(), logf(), но как-то странно работает. send_base массив 16 битных слов.
В таком виде не работает.
Код
volatile float x=((adc_ext_result[i]/5*20000.0)/(65535.0-adc_ext_result[i]/5));
send_base[adc_ext_index[i]]=logf(x);

x=21521.0; log(x)= 65535.

А так работает:
Код
volatile float x=((adc_ext_result[i]/5*20000.0)/(65535.0-adc_ext_result[i]/5));
float r=21521.0;
send_base[adc_ext_index[i]]=logf(r);


logf®=9;

arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors) 4.8.4 20140725 (release) [ARM/embedded-4_8-branch revision 213147]
на работе пробовал компилить другим тулчайном резльтат тот же. Не могу понять где копать.
AHTOXA
А у вас стек выровнен на 8 байт?
-Игорь-
был выровнен на 4 байта. Поставил 8. Ничего не изменилось. Попробовал стек увеличить до 2к. Тоже никаких изменений.
Пробовал другие функции , тоже не работают. Пробовал log10, sin.
подключаю:
#include <math.h>
AHTOXA
Оставьте 8, так надо.
-lm линкеру не забыли?
Ещё смутно помню, что -lm должна быть последней из библиотек в командной строке линкера. Но тут могу что-то путать.
-Игорь-
-lm поставил последним ключом. Поставил 8. Не считает .
Удивительно, что сама по себе библиотека работает.

Ага. Что-то стало прояснятся. У меня эта функция находилась в прерывании, я вытащил ее в майн. И нашел глюк. Значения для функции меняются произвольным образом, т.е. похоже где-то косяк, который в функцию кидает похоже отрицательные числа. Спасибо огромное за помощь. А то уже руки опустились.
scifi
Кстати, выражение "adc_ext_result[i]/5*20000.0" выглядит совсем плохо. Я бы написал "adc_ext_result[i]*(20000.0f/5)".
AHTOXA
Да не за чтоsm.gif
Кстати, если вы по какой-то причине хотите считать исключительно с float (ну, быстродействие, размер кода, или что-то ещё), то константы пишите с суффиксом f: 65535.0f. Без этого у вас в правой части выражения всё считается в double, и только потом конвертируется в float.
-Игорь-
Спасибо про суффикс попробую запомнить, float использую да, для скорости.

Все таки полное непонимание. Значит вчера я усомнился, что в функцию попадают корректные данные. Сегодня стал проверять и оказалось, что не понимаю в чем эти данные некорректные. Я могу вывести на дисплей данные, которые находятся в массиве send_base. Массив uint16_t. Выводить на дисплея я умею только uint16_t.
Если код такой:
Код
float r=((adc_ext_result[i]*(20000.0f/5.0f))/(65535.0f-adc_ext_result[i]/5.0f));
send_base[adc_index[0]]=r;
send_base[adc_ext_index[i]]=logf(r);

то, значение r плавает около 12570 (это результат измерения ацп)
значение logf® всегда 65535.
Меняю код на следущий:
Код
float r=((adc_ext_result[i]*(20000.0f/5.0f))/(65535.0f-adc_ext_result[i]/5.0f));
uint16_t x=(uint16_t)r;
send_base[adc_index[0]]=x;
send_base[adc_ext_index[i]]=logf(x);

значение x такое же, а вот значение функции logf(x) становится правильным =9.
Не понимаю, что происходит.

Так тоже работает:
send_base[adc_ext_index[i]]=logf((uint16_t)r);



Наверно самое главное забыл сказать. У меня контроллер stm32f051. Т.е. cortex-m0. Может какие-то специальные ключи нужны для компилятора?
Я ставлю ключи: -mcpu=cortex-m0 -mthumb
sidy
Цитата(scifi @ Oct 21 2014, 23:05) *
Кстати, выражение "adc_ext_result[i]/5*20000.0" выглядит совсем плохо. Я бы написал "adc_ext_result[i]*(20000.0f/5)".

А я попробовал бы записать "adc_ext_result[i]*4000.0f"
Golikov A.
вообще то
log(12570) != 9;
он равен
9.4390683015842931064461706132924

вы уверен что косяк в момент вычисления log, а не в момент перевода флота в целое? Просто если флот на входе воспринимается как инт, то есть 2 ичное представление, то получается огромное число и косяк...

я бы для верности сделал

(int)log((float)x);

кстати вы уверены что у вас в библиотеки флотовый логарифм? и нет ли варнинга о неявном его объявлении? потому что если так, то иногда среды все неявные функции считают объявленными с интовым входом и что не пихай думают что это инт.

-Игорь-
Я могу посмотреть только целые, поэтому и вижу 9. Умножаю результат на 1000, вижу для х=12866, logf(x)*1000=9462, это вот прямо сейчас на диcплее.
Т.е. если в функцию кладу целое, то считается нормально, если флоат, как требует объявление функции то результат - переполнение.
Я понимаю, что какие-то траблы с преобразованием целое-флоат. Но в каком месте и почему не понимаю.

варнингов нет. толчайн брал здесь - https://launchpad.net/gcc-arm-embedded
gnu math: Function: float logf (float x)
сейчас посмотрю исходники тулчайна если найду, но я думаю, что траблы где-то в другом месте.

Тулчайн оказывается стоит Sourcery. А по ссылке, которую приводил, стоит дома. Но с обоими тулчайнами результат одинаков.

в math.h
extern float logf _PARAMS((float));
Golikov A.
а что такое _PARAMS ?

попробуйте так, ну чтобы наверняка?
answer = (int)log( ((float)x) );

если криво будет, то остается только одно, что в библиотеке стоит какая-то левая функция на точке входа logf, которая считает что-то не то
-Игорь-
Криво.
-Игорь-
Глюк мой. Плохое понимание преобразования типов.
Ожидал, что преобразование из плавающего в целое беззнаковое будет осуществляться как в знаковое, оказывается знак просто откидывается. Т.е. значение 21521, на самом деле было -21521.0. Поэтому и было переполнение.
Всем спасибо за внимание и помощь.
Golikov A.
странно, обычно знаковое преобразуется в знаковое

float a = -21521.0;
int b = (int)a == -21521;
причем дробная часть просто отбрасывается, потому округление положительных и отрицательных в разные стороны

неужели в gcc не так?
-Игорь-
Да. Вы правы. Проверил, преобразовывает именно так.
Тогда вообще ничего не понимаю. Может быть кроме преобразования отрицательного в целое безнаковое еще и переполнение было?

Да. если происходит переполнение, то результат не предсказуем.
scifi
Цитата(-Игорь- @ Oct 22 2014, 14:48) *
Проверил, преобразовывает именно так.

Каждый раз веселюсь, когда вижу, как свойства языка Си снова открывают эмпирическим путём :-)
А книжку почитать не судьба? В том же K&R всё хорошо написано. Иначе будете по этим граблям блуждать и дальше.
-Игорь-
Читал, не единожды. Видимо голова небольшого объема.
Я собственно оветил, чтобы отметить, что с компилятором как всегда все ок.
Golikov A.
Цитата
Каждый раз веселюсь, когда вижу, как свойства языка Си снова открывают эмпирическим путём


тут это уже на уровне руки помнят. То есть всю жизнь было так и я всегда это применял, но когда увидел запись что нет, задумался... вдруг это не закон а просто всегда везлоsm.gif. Такой фигни много бывает, стирается из памяти источник знаний, остаются только факты и опыт применений. Весело, возможно, но что не стыдно сто пудовоsm.gif...

У флоат если мне не изменяет память есть спец символ +- бесконечность. Может на него так log реагирует? exp(65535) - это прям дофига-дофигища, и число уж больно интересное 16 единичек...

проверил, виндовый калькулятор на e^65535 честно заявляет переполнение, хотя и на 65534 тоже), где то в районе 22000 предел наступает. При этом я уверен он считает в даблах, так что для флота переполнение еще раньше. Скорее всего полученный ответ - это какой-то флаг...

scifi
Цитата(Golikov A. @ Oct 22 2014, 19:36) *
Такой фигни много бывает, стирается из памяти источник знаний, остаются только факты и опыт применений. Весело, возможно, но что не стыдно сто пудовоsm.gif...

Расскажу по секрету: есть такие полезные штуки - "справочники" называются. Очень помогают. А в наш век тырнетов и гуглов они все на расстоянии вытянутой руки. Пользуйтесь, пока санкции тырнет не отрубили :-)
Golikov A.
вы все известные вам факты, от которых вы забыли источник, пробиваете по гуглу?
scifi
Цитата(Golikov A. @ Oct 22 2014, 21:33) *
вы все известные вам факты, от которых вы забыли источник, пробиваете по гуглу?

Скажем так: перед обращением к помощи форума обязательно сверяюсь со справочниками. Кстати, что-то давно не обращался :-)
Golikov A.
не делаете ничего нового, наверное? wink.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.