Математика Ардуино

AlexanderNO
Offline
Зарегистрирован: 08.11.2018
Потребовалось мне несколько математических функций для расчетов. Решил использовать имеющуюся в IDE библиотеку math.h. Проверил - всё вроде считает, но дернуло проверить на точность (когда-то давно так программируемые калькуляторы проверялись). Собственно схема проверки простая - вычисляется косинус (или любая тригонометрическая функция) большого угла, выраженного в радианах, и сравнивается с "эталоном". В качестве аргумента выбрал 123456789.  Заодно выводится число пи (оно есть в библиотеке) и опять сравнивается с эталонным. Вывожу 9 знаков в сериал мониторе. Запустил маленький скетчик
double double__x = 123456789.0 ;
void setup() {
   Serial.begin(9600);
   Serial.print("cos double__x = ");
   Serial.println (cos (double__x), 9 ); // returns cosine of x
   Serial.print("Pi = ");
   Serial.println (M_PI, 9 ); // returns PI
}
void loop() {
  // put your main code here, to run repeatedly:
}
cos double__x = -0.278581023
Pi = 3.141592741
и сравнил с вычислениями виндосовского калькулятора. Вот результаты калькулятора. Косинус: 0,14025968153390962995065549327877. ПИ:3,1415926535897932384626433832795. 
Лезу в файл math.h и вижу:
/** The constant \a pi. */
#define M_PI 3.14159265358979323846 /* pi */ 
Полностью совпадает с тем, что выдал калькулятор, а в выводе в сериал ошибка в 7-м знаке после запятой. О вычислении косинуса вообще молчу.
Где ошибка и как правильно считать не могу разобраться.
kalapanga
Offline
Зарегистрирован: 23.10.2016

Неудачный тестовый пример. Вы слишком большую точность от типа double (здесь он же float) хотите - 9 знаков. Он не умеет столько. Вот здесь пишут 6-7 знаков всего http://arduino.ru/Reference/Float Выведите на печать само double__x без всяких форматов - всё сами увидите. А несколько радиан для косинуса - вот и совсем непохожий результат. Ну и пи только до соответствующего знака стоит сравнивать.

 

AlexanderNO
Offline
Зарегистрирован: 08.11.2018

kalapanga пишет:

Неудачный тестовый пример. Вы слишком большую точность от типа double (здесь он же float) хотите - 9 знаков. Он не умеет столько. Вот здесь пишут 6-7 знаков всего http://arduino.ru/Reference/Float Выведите на печать само double__x без всяких форматов - всё сами увидите. А несколько радиан для косинуса - вот и совсем непохожий результат. Ну и пи только до соответствующего знака стоит сравнивать.

Ну, хорошо, а для кого в библиотеке пи до 20-го знака?

b707
Offline
Зарегистрирован: 26.05.2017

AlexanderNO пишет:

Ну, хорошо, а для кого в библиотеке пи до 20-го знака?

наверно для тех, кто уверен, что "чем больше знаков - тем точнее"

kalapanga
Offline
Зарегистрирован: 23.10.2016

Например, для Arduino Due тип double не 4-х, а 8-байтовый.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

https://gcc.gnu.org/wiki/avr-gcc#Type_Layout

 

В avr-GCC нет типа double. Весь твой пример - нормально посчитан на float. ;))))))))

;))))) пичалько! ;))))))))

SLKH
Offline
Зарегистрирован: 17.08.2015

AlexanderNO пишет:

Потребовалось мне несколько математических функций для расчетов. Решил использовать имеющуюся в IDE библиотеку math.h. Проверил - всё вроде считает, но дернуло проверить на точность (когда-то давно так программируемые калькуляторы проверялись). Собственно схема проверки простая - вычисляется косинус (или любая тригонометрическая функция) большого угла, выраженного в радианах, и сравнивается с "эталоном". В качестве аргумента выбрал 123456789.  Заодно выводится число пи (оно есть в библиотеке) и опять сравнивается с эталонным. Вывожу 9 знаков в сериал мониторе. Запустил маленький скетчик
double double__x = 123456789.0 ;
void setup() {
   Serial.begin(9600);
   Serial.print("cos double__x = ");
   Serial.println (cos (double__x), 9 ); // returns cosine of x
   Serial.print("Pi = ");
   Serial.println (M_PI, 9 ); // returns PI
}
void loop() {
  // put your main code here, to run repeatedly:
}
cos double__x = -0.278581023
Pi = 3.141592741
и сравнил с вычислениями виндосовского калькулятора. Вот результаты калькулятора. Косинус: 0,14025968153390962995065549327877. ПИ:3,1415926535897932384626433832795. 
Лезу в файл math.h и вижу:
/** The constant \a pi. */
#define M_PI 3.14159265358979323846 /* pi */ 
Полностью совпадает с тем, что выдал калькулятор, а в выводе в сериал ошибка в 7-м знаке после запятой. О вычислении косинуса вообще молчу.
Где ошибка и как правильно считать не могу разобраться.

в math.h: #define M_PI 3.14159265358979323846

в  Aduino.h:  #define PI 3.1415926535897932384626433832795 

Вопрос "на кой хрен нужна эта точность?", остается.

 

Для подавляющего большинство реальных механизмов хватает точности логарифмической линейки - т.е. три значащих цифры.

AlexanderNO
Offline
Зарегистрирован: 08.11.2018

b707 пишет:

AlexanderNO пишет:

Ну, хорошо, а для кого в библиотеке пи до 20-го знака?

наверно для тех, кто уверен, что "чем больше знаков - тем точнее"

Ну не надо так то. Для любой системы есть свои ограничения. Косинус с большИм аргументом может оказаться большой ошибкой и привести к последствиям, если не знать ограничений. А здесь ошибка уже в первом знаке. 

Да и непонятно откуда берутся "хвосты" после 7 знака. Сейчас отправил в сериал 13 знаков после запятой, получил 13 знаков: 

cos double__x = -0.2785810232162
Pi = 3.1415927410125
 
 
SLKH
Offline
Зарегистрирован: 17.08.2015

AlexanderNO пишет:

Ну, хорошо, а для кого в библиотеке пи до 20-го знака?

Предположим, у нас есть кругдый участок диаметром 100 метров +/- 20см.

Если мы знаем пи с точностью 31 знак после запятой, мы сможем рассчитать длину забора намного точнее, чем при 20 знаках. Это позволит нам правильно заказать кол-во рулонов сетки.

 

kalapanga
Offline
Зарегистрирован: 23.10.2016

Вы вывели в сериал само Ваше число double__x ? Вы поняли, почему там не 123456789.0 ?

Почитайте что-нибудь про двоичное представление вещественных чисел. Не любое число можно точно сохранить в вещественном формате. Вам и выводится приближенное представление.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

AlexanderNO пишет:
а в выводе в сериал ошибка в 7-м знаке после запятой
Правильно. Четырёхбайтовый float даёт 6 знаков и не больше. Выводить при этом Вы можете хоть 20 - это Ваши заморочки.

AlexanderNO пишет:

Ну, хорошо, а для кого в библиотеке пи до 20-го знака?

Это универсальная константа и для 8-байтового double и для больших (по объёму памяти) чисел.

По поводу же косинуса - нормальное накапливание ошибки. Слыхали про то, как американцы под 30 человек убитыми потеряли из-за накапливаюзщейся ошибки в прошивке "Патриотов". Ото ж.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

AlexanderNO пишет:

Да и непонятно откуда берутся "хвосты" после 7 знака. Сейчас отправил в сериал 13 знаков после запятой, получил 13 знаков: 

cos double__x = -0.2785810232162
Pi = 3.1415927410125
 
 

Блин! Чукча не читатель?

Я УЖЕ написал, что НЕТ В avr-gcc ТИПА DOUBLE.

Он совпадает с float, то есть 32 бита. Вот чего непонятного я написал?????

Точно нужно тест на психические отклонения при регистрации проводить.

С желаетмой тобой точность в 64 бита СЧИТАТЬ НА АРДУИНО МОЖНО ТОЛЬКО НА СТОРОННИХ библиотеках.

(может капсом дойдет ???)

AlexanderNO
Offline
Зарегистрирован: 08.11.2018

wdrakula пишет:

AlexanderNO пишет:

Да и непонятно откуда берутся "хвосты" после 7 знака. Сейчас отправил в сериал 13 знаков после запятой, получил 13 знаков: 

cos double__x = -0.2785810232162
Pi = 3.1415927410125
 
 

Блин! Чукча не читатель?

Я УЖЕ написал, что НЕТ В avr-gcc ТИПА DOUBLE.

Он совпадает с float, то есть 32 бита. Вот чего непонятного я написал?????

Точно нужно тест на психические отклонения при регистрации проводить.

С желаетмой тобой точность в 64 бита СЧИТАТЬ НА АРДУИНО МОЖНО ТОЛЬКО НА СТОРОННИХ библиотеках.

(может капсом дойдет ???)

Вы специально стараетесь нахамить незнакомому Вам человеку? Я Вас обидел чем-то? Будьте поспокойнее.

AlexanderNO
Offline
Зарегистрирован: 08.11.2018

ЕвгенийП пишет:

AlexanderNO пишет:
а в выводе в сериал ошибка в 7-м знаке после запятой
Правильно. Четырёхбайтовый float даёт 6 знаков и не больше. Выводить Вы можете хоть 20 - это Ваша заморочки.

AlexanderNO пишет:

Ну, хорошо, а для кого в библиотеке пи до 20-го знака?

Это универсальная константа и для 8-байтового double и для больших (по объёму памяти) чисел.

По поводу же косинуса - нормальное накапливание ошибки. Слыхали про то, как американцы под 30 человек убитыми потеряли из-за накапливаюзщейся ошибки в прошивке "Патриотов". Ото ж.

Спасибо за ответ. Да, я знаю, что в косинусе ошибка накапливается, поэтому и проверял. А по поводу ПИ были у меня программы (не для ардуино, конечно), где ПИ вычислялось как 4*atan(1). Здесь попробовал и началось...

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

AlexanderNO пишет:

Вы специально стараетесь нахамить незнакомому Вам человеку? Я Вас обидел чем-то? Будьте поспокойнее.

Я один, "вы"-кать не нужно ;)))).

Я неспокоен потому, что уже ответил, а обсуждение продолжается. Могу спокойнее объяснить, но мне кажется, что разжевывание, как для даунов, оскорбляет собеседника юольше, чем грубость.

В avr-gcc, а это именно тот компилятор, который применается в Ардуино ИДЕ, не реализован 64 битный double, ссылку на документацию для подтверждения я отправил в первом, вежливом посте.

Это означает, что объявляя double переменную, она все равно живет как флоат. И все вычислени - как флоат. Если ты перепишешь свой пример с объявлениями "флоат", то получишь именно такой вывод, как получил с дабл.

Вот смотри, что печатает ардуина:

x=123456790.000000000
cos(x)=   -0.278581020
Pi=    3.141592700

то есть видишь ли ты, как изменилось число 1234567789.0? И косинус посчитан с накапливающейся ошибкой.

Константа указана единообразно для всех реализаций. Это же просто исходник от libc.

====================

Мне кажется, что такое разжевывание унизительно для тебя. После моего первого ответа все это и так понятно, нет? Сорри, но не я тебя таким обидчивым воспитал.

AlexanderNO
Offline
Зарегистрирован: 08.11.2018

wdrakula пишет:

AlexanderNO пишет:

Вы специально стараетесь нахамить незнакомому Вам человеку? Я Вас обидел чем-то? Будьте поспокойнее.

Я один, "вы"-кать не нужно ;)))).

Я неспокоен потому, что уже ответил, а обсуждение продолжается. Могу спокойнее объяснить, но мне кажется, что разжевывание, как для даунов, оскорбляет собеседника юольше, чем грубость.

В avr-gcc, а это именно тот компилятор, который применается в Ардуино ИДЕ, не реализован 64 битный double, ссылку на документацию для подтверждения я отправил в первом, вежливом посте.

Это означает, что объявляя double переменную, она все равно живет как флоат. И все вычислени - как флоат. Если ты перепишешь свой пример с объявлениями "флоат", то получишь именно такой вывод, как получил с дабл.

Вот смотри, что печатает ардуина:

x=123456790.000000000
cos(x)=   -0.278581020
Pi=    3.141592700

то есть видишь ли ты, как изменилось число 1234567789.0? И косинус посчитан с накапливающейся ошибкой.

Константа указана единообразно для всех реализаций. Это же просто исходник от libc.

====================

Мне кажется, что такое разжевывание унизительно для тебя. После моего первого ответа все это и так понятно, нет? Сорри, но не я тебя таким обидчивым воспитал.

Да что Вы так переживаете-то? Я уже давно, еще до Вашего вмешательства, понял и про синус и про косинус и про float. Так что не стОило так уж разжевывать и волноваться.  

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

По моему это уже стоит сделать классикой:

http://arduino.ru/forum/programmirovanie/vyvod-float-na-serial-monitor#c...

 

AlexanderNO
Offline
Зарегистрирован: 08.11.2018

Хотел я на Ардуино попробовать одну программу, которую еще в 2011 написАл для ПК. 

Бегать с ноутбуком и телескопом не очень удобно. Поэтому было желание переложить на Ардуино. Но посмотрев на исходники, понял, что не потянет оно, даже с упрощенными формулами. Там несколько важных констант требуют более 6 знаков после запятой. Вот и вся история вопроса о точности вычислений. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

AlexanderNO пишет:
Поэтому было желание переложить на Ардуино.
Почему не на смартфон? Он всегда с собой, а ардуино ещё таскать надо.

AlexanderNO
Offline
Зарегистрирован: 08.11.2018

Для смартфона есть программы, но они только для вычисления звездного времени, а тут всё, включая координаты объектов. Достал телескоп и наводи куда надо. Там же отдельная база данных по кооодинанам объектов и мест наблюдения. А для смартфона я программ не пишу. Хотел, но старый уже. В этом году 69 стукнет(((

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Если не делаешь секрета из кода, то мне лет меньше - 49 и с переносом кода на Андроид я помогу задаром. Мне и самому интересно, а ты мне телескоп посоветуешь для начала - до 50 т.р что-нибудь, а то жена убъет ;))). Почта - мой ник на жмейле.

AlexanderNO
Offline
Зарегистрирован: 08.11.2018

У меня исходники на VB. Годится?

А телескоп я никому не советую - дорогая игрушка. На пару-тройку сезонов, а потом будет на полке. Тем более самое интересное на небе зимой, когда холодно и смотреть нЕгде - около больших городов небо засвечено, облачность почти постоянная. Осенью еще можно, даже с конца августа, но сыро - телескоп потеет на природе. В общем одни неприятности. Сам телескоп с монтировкой - это только начало, потом пойдут окуляры, линзы, призмы, фильтры переходники всякие, желание заняться астрофотографией. Кукла барби с Кеном. Ну, как-то так. А лучше всего потусоваться на астрофорумах для начала. Я бы посоветовал от себя начать с обычного бинокля с небольшим увеличением - для созвездий. Если увлечет, то дальше можно думать.

SLKH
Offline
Зарегистрирован: 17.08.2015

AlexanderNO пишет:

Для смартфона есть программы, но они только для вычисления звездного времени, а тут всё, включая координаты объектов. Достал телескоп и наводи куда надо. Там же отдельная база данных по кооодинанам объектов и мест наблюдения. А для смартфона я программ не пишу. Хотел, но старый уже. В этом году 69 стукнет(((

а в какой-нибудь опенофис для андроида формул навтыкать? вроде несложно (если формулы знать).

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

AlexanderNO пишет:

 Поэтому было желание переложить на Ардуино. Но посмотрев на исходники, понял, что не потянет оно, даже с упрощенными формулами. Там несколько важных констант требуют более 6 знаков после запятой. Вот и вся история вопроса о точности вычислений. 

На ардуине можно хоть до 20 знаков после запятой считать. Прсто медленнее будет. Какая конкретно точность нужна и какие функции нужны?

AlexanderNO
Offline
Зарегистрирован: 08.11.2018

SLKH пишет:

а в какой-нибудь опенофис для андроида формул навтыкать? вроде несложно (если формулы знать).

Да, ребята, спасибо ничего страшного. Все это от лени как всегда. Если есть бумажка с координатами объектов, то можно только со звездным временем на смартфоне. 

AlexanderNO
Offline
Зарегистрирован: 08.11.2018

Если кому-нибудь интересна тема астрономии и программирования, рекомендую эту книгу (качать с CD). Есть программы на СИ.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

ЕвгенийП пишет:

Четырёхбайтовый float даёт 6 знаков и не больше.

Да?

Аккуратные подсчеты показывают несколько иное. (разумеется, если речь идет о десятичных знаках)

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

AlexanderNO пишет:

У меня исходники на VB. Годится?

А телескоп я никому не советую - дорогая игрушка. На пару-тройку сезонов, а потом будет на полке. Тем более самое интересное на небе зимой, когда холодно и смотреть нЕгде - около больших городов небо засвечено, облачность почти постоянная. Осенью еще можно, даже с конца августа, но сыро - телескоп потеет на природе. В общем одни неприятности. Сам телескоп с монтировкой - это только начало, потом пойдут окуляры, линзы, призмы, фильтры переходники всякие, желание заняться астрофотографией. Кукла барби с Кеном. Ну, как-то так. А лучше всего потусоваться на астрофорумах для начала. Я бы посоветовал от себя начать с обычного бинокля с небольшим увеличением - для созвездий. Если увлечет, то дальше можно думать.

1. Про VB, мне все равно. Знаешь ли старую байку про Вяч. В. Ива'нова, великого лингвиста? Как-то Комо Иванова спросили: "А сколько языков Вы знаете?". Вячеслав Всеволодович замялся на мнгновение и уверенно ответил: "Все".

Про себя с таким пафосом не скажу... но все-же. ;)))))

2. Я в МО живу в частном доме. Проблемм с небом не имею. Как-то с женой, по спонтанному решению, сели в машину и поехали в Норвегию, на Норд-кап (самая северная точка Европы, очень далеко за полярным кругом), в феврале 2014, ловить северное сияние ;))) на старой ржавой праворульной Мазде. Зато было весело. (если у читателя недопонимание про визы возникнет, то длинный шенген был давно открыт, просто садись и рули). Ошибку сделал - небо чише дальше от моря. Надо было в Альту ехать, а не на Магерёйю. Чуть-чуть было сияния, но мало совсем - пурга, и луна яркая мешала сильно засветкой.

И бинокль и труба есть, и Юпитер я в трубу смотрю, а хочу и спутники его разглядеть. Вот просто и поинтересовался, что можно посоветовать за небольшие деньги - до 50 т.р.?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

AlexanderNO пишет:

Хотел я на Ардуино попробовать одну программу, которую еще в 2011 написАл для ПК. 

Бегать с ноутбуком и телескопом не очень удобно. Поэтому было желание переложить на Ардуино. Но посмотрев на исходники, понял, что не потянет оно, даже с упрощенными формулами. Там несколько важных констант требуют более 6 знаков после запятой. Вот и вся история вопроса о точности вычислений. 

1. Когда мы имеем дело с принципиально ограниченными величинами (углы, время, дата) рациональнее использовать не float/double, а fixed или вообще целые числа.

2. Если все лень и хочется именно double, то такие имеются в Arduino Due или Stmduino.

3. Если хочется именно double и AVR, можно поискать соответствующие библиотеки. Если уж на intel8080 с его 2 МГц и 0.5 MIPS были 8-байтовые с плавающей точкой, то уж на 16 МГц AVR при 16 MIPS это в случае единичных вычислений не должно быть непростительно медленно.

В общем, не рассматриваю ситуацию как тупиковую. Но в любом случае, Вам бы разобраться, как хранятся числа в компьютере, чтобы правильно спланировать работу и не наделать глупых ошибок.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

andriano пишет:

Аккуратные подсчеты показывают несколько иное. (разумеется, если речь идет о десятичных знаках)

Да, кто б спорил - то? Вот только пользоваться уверенно можно именно 6-ю, а не 7.2 знаками :)

Гриша
Offline
Зарегистрирован: 27.04.2014
andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

ЕвгенийП пишет:

andriano пишет:

Аккуратные подсчеты показывают несколько иное. (разумеется, если речь идет о десятичных знаках)

Да, кто б спорил - то? Вот только пользоваться уверенно можно именно 6-ю, а не 7.2 знаками :)

Уверенно можно пользоваться только двоичными разрядами. Десятичные - так, для грубой оценки.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

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

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

А чем я, по-вашему, пользуюсь? Ж8( )

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Не знаю, я как-то даже не думал об этом. Пользуйтесь, на здоровье, чем Вам удобно :)

Секешфехервар
Секешфехервар аватар
Offline
Зарегистрирован: 06.09.2018

Неудачный пример я конечно в программировании новичок , но совершенно точно могу вам сказать с металлопрокатом никогда нельзя быть уверенным , к примеру в 6 метровой трубе может оказаться от 6100мм до 5750мм а про рабицу я вообще боюсь представить , так что программирование вам тут не поможет ))))