Форум программистов, компьютерный форум, киберфорум
Arduino
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
4 / 5 / 2
Регистрация: 02.04.2018
Сообщений: 488
1

Баг в среде ардуино

02.06.2022, 12:39. Показов 491. Ответов 2
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Нашёл баг в среде Ардуино. Может быть конечно у меня корявые руки, но в принципе как говориться, тут ломаться-то нечему.

Есть функция pow(x, 3); = и вот она творит чудеса.

если вызвать её и посчитать к примеру pow(-48, 3)/48; результат вычислений будет -2304 всё верно, но стоит заключить в цикл и перебирать переменную x, как начинается магия. почему-то результат вычислений функции -2303, хотя с квадратом данная функция считает всё правильно. Решил разобраться с этим вопросом и выяснил что при значениях -48 функция pow(x,3) выдаёт ответ -110591 (а должно быть -110592) поэтому при делении получается число -2 303,9791666666666666666666666667 что даёт округление к ближайшему меньшему -2303. Если заменить функцию простым умножением x*x*x/48 = то результат вычислений сразу становится правильным.

Интересный баг, по отдельности функция вычисляет число верно, но стоит её загнать в цикл, как происходит магия кривого вычисления.
Немного дописав программу увидел подобный баг в числах
-60, -48, -36, и других числах кратные 12... что за... магия...

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
signed long y_1 = 0;
signed long y_2 = 0;
 
void setup() {
  Serial.begin(9600);
   for (signed long x = -60; x<60; x++) {
     y_1 = x * x * x / 48;
     y_2 = pow(x,3)/48;
     Serial.print(x);
     Serial.print(":->");
     Serial.print(y_1);
     Serial.print(",");
     Serial.println(y_2);
   }
}
 
 
void loop() {}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
02.06.2022, 12:39
Ответы с готовыми решениями:

Баг Ардуино при вычислениях
Есть ли способ как исправить баг при вычислениях на Ардуино? float gps_last_x = 48.487331;...

В среде ардуино нет возможности выбрать порт
Здравствуйте помогите пожалуйста

Как проверить реле к ардуино без ардуино
Собственно вопрос в названии. Дело в том что реле пришло по почте раньше чем само ардуино. Так как...

ESP32 в среде ардуино WEB server + MQTT
Уважаемые!!! Подскажите в общих чертах, или, если есть ссылка на пример. Нужно реализовать на...

2
4 / 5 / 2
Регистрация: 02.04.2018
Сообщений: 488
02.06.2022, 12:58  [ТС] 2
Кстати, добавлю, на чистом языке C++ он считает верно, значит виноват сам компилятор дурины и его корявая функция pow?
Баг в среде ардуино
0
634 / 389 / 75
Регистрация: 21.09.2008
Сообщений: 1,328
05.06.2022, 15:53 3
Цитата Сообщение от SergeyKagen Посмотреть сообщение
Нашёл баг в среде Ардуино.
Хм. Посмотрим.
Цитата Сообщение от SergeyKagen Посмотреть сообщение
Может быть конечно у меня корявые руки, но в принципе как говориться, тут ломаться-то нечему.
Настоящий критерий истины - практика, верно? Вот и напишем проверку на чистом Си с использованием стандартной библиотеки avr-libc-2.0.0 и компилятора GCC-11.1 для AVR, запустим под настоящим "железом" в виде ATmega8A. У Вас какая версия компилятора была использована?
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <math.h>
#include <avr/io.h>
#include <stdint.h>
#include <string.h>
#include "uart.h"
 
#define BUFSIZE 12
#define SERIAL_SPEED (57600)
 
signed long y_1, y_2;
 
char* intToStr(int32_t Number) {
  static char txtBuf[BUFSIZE];
  char *Buf = txtBuf;
  uint8_t IntLen = 1;
  uint16_t Power = 1;
 
  memset(txtBuf, 0, BUFSIZE);
  if (0 == Number) {
    *Buf = '0';
    return txtBuf;
  }
  if (Number < 0) {
    Number = ~Number + 1;
    *Buf++ = '-';
  }
  do {
    Power *= 10;
    if (Power <= Number)
      ++IntLen;
  } while (Power < Number);
  Buf += IntLen - 1;
  do {
    *Buf = (char)(Number % 10 + '0');
    Number = Number / 10;
    --Buf;
  } while (0 != Number);
  return txtBuf;
}
 
int main(void) {
  DDRD = _BV(PD1); // TXD на выход для вывода на UART
  PORTD = 0;
  uartInit(SERIAL_SPEED);
  while (1) {
    for (signed long x = -60; x < 60; x++) {
      y_1 = x * x * x / 48;
      y_2 = pow(x, 3) / 48;
      uartSendString(intToStr(x));
      uartSendString(":->");
      uartSendString(intToStr(y_1));
      uartSendChar(',');
      uartSendString(intToStr(y_2));
      uartSendChar('\n');
    }
    uartSendString("pow(-24.0, 3.0)/48.0 = ");
    uartSendString(intToStr(pow(-24.0f, 3.0f) / 48.0f));
    uartSendChar('\n');
    
    uartSendString("pow(-12.0, 3.0)/48.0 = ");
    uartSendString(intToStr(pow(-12.0f, 3.0f) / 48.0f));
    uartSendChar('\n');
    
    uartSendString("pow(12.0, 3.0)/48.0 = ");
    uartSendString(intToStr(pow(12.0f, 3.0f) / 48.0f));
    uartSendChar('\n');
    
    uartSendString("pow(36.0, 3.0)/48.0 = ");
    uartSendString(intToStr(pow(36.0f, 3.0f) / 48.0f));
    uartSendChar('\n');
 
    uartSendString("pow(48.0, 3.0)/48.0 = ");
    uartSendString(intToStr(pow(48.0f, 3.0f) / 48.0f));
    uartSendChar('\n');
  }
}
Выдача в терминал:
Кликните здесь для просмотра всего текста
-60:->-4500,-4500
-59:->-4278,-4278
-58:->-4064,-4064
-57:->-3858,-3858
-56:->-3658,-3658
-55:->-3466,-3466
-54:->-3280,-3280
-53:->-3101,-3101
-52:->-2929,-2929
-51:->-2763,-2763
-50:->-2604,-2604
-49:->-2451,-2451
-48:->-2304,-2303
-47:->-2162,-2162
-46:->-2027,-2027
-45:->-1898,-1898
-44:->-1774,-1774
-43:->-1656,-1656
-42:->-1543,-1543
-41:->-1435,-1435
-40:->-1333,-1333
-39:->-1235,-1235
-38:->-1143,-1143
-37:->-1055,-1055
-36:->-972,-971
-35:->-893,-893
-34:->-818,-818
-33:->-748,-748
-32:->-682,-682
-31:->-620,-620
-30:->-562,-562
-29:->-508,-508
-28:->-457,-457
-27:->-410,-410
-26:->-366,-366
-25:->-325,-325
-24:->-288,-287
-23:->-253,-253
-22:->-221,-221
-21:->-192,-192
-20:->-166,-166
-19:->-142,-142
-18:->-121,-121
-17:->-102,-102
-16:->-85,-85
-15:->-70,-70
-14:->-57,-57
-13:->-45,-45
-12:->-36,-35
-11:->-27,-27
-10:->-20,-20
-9:->-15,-15
-8:->-10,-10
-7:->-7,-7
-6:->-4,-4
-5:->-2,-2
-4:->-1,-1
-3:->0,0
-2:->0,0
-1:->0,0
0:->0,0
1:->0,0
2:->0,0
3:->0,0
4:->1,1
5:->2,2
6:->4,4
7:->7,7
8:->10,10
9:->15,15
10:->20,20
11:->27,27
12:->36,35
13:->45,45
14:->57,57
15:->70,70
16:->85,85
17:->102,102
18:->121,121
19:->142,142
20:->166,166
21:->192,192
22:->221,221
23:->253,253
24:->288,287
25:->325,325
26:->366,366
27:->410,410
28:->457,457
29:->508,508
30:->562,562
31:->620,620
32:->682,682
33:->748,748
34:->818,818
35:->893,893
36:->972,971
37:->1055,1055
38:->1143,1143
39:->1235,1235
40:->1333,1333
41:->1435,1435
42:->1543,1543
43:->1656,1656
44:->1774,1774
45:->1898,1898
46:->2027,2027
47:->2162,2162
48:->2304,2303
49:->2451,2451
50:->2604,2604
51:->2763,2763
52:->2929,2929
53:->3101,3101
54:->3280,3280
55:->3466,3466
56:->3658,3658
57:->3858,3858
58:->4064,4064
59:->4278,4278
pow(-24.0, 3.0)/48.0 = -288
pow(-12.0, 3.0)/48.0 = -36
pow(12.0, 3.0)/48.0 = 36
pow(36.0, 3.0)/48.0 = 972
pow(48.0, 3.0)/48.0 = 2304
Действительно, на числах кратных 12, в цикле for() функция pow() "ломается", занижая результат. Однако если подставить числа непосредственно в аргументы функции pow, например, (-24.0, 3.0) / 48.0, то вывод будет верным. Согласно спецификации, аргументы и возвращаемый результат функцией pow() имеет тип double. В цикле for() аргументы и результат имеют целочисленный тип со знаком. Аргумент x у Вас приращивается на целочисленную единицу (+1), а не +1.0f (если понимаете эту тонкость).
Строго говоря, выявленная особенность находится не в среде Arduino, а в компиляторе AVR-GCC, который используется для сборки ПО.
Вспомогательная библиотечка UART для вывода в консоль, файлы прошивок примера под ATmega8A и ATmega328p приложены в архиве.
Вложения
Тип файла: zip kagen.zip (28.4 Кб, 3 просмотров)
0
05.06.2022, 15:53
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
05.06.2022, 15:53
Помогаю со студенческими работами здесь

Связь по Блютузу Андроид и Ардуино, команды с Ардуино
Есть https://cxem.net/arduino/arduino64.php , там связь...

Баг в программе. Без цикла работает нормально. С циклом выдает баг
Здравствуйте. Пишу программу. И как не пытался ее переписать, как дохожу до момента включения в код...

std::regex : баг на сайте или баг компилятора?
http://en.cppreference.com/w/cpp/regex/regex_match этот код выкидывает throw... Добавлено через...

Баг asio? или баг TCP стека?
всем привет. повстречался с очень странным багом. и не могу определить кто бажит, asio, или...

Забавный баг Делфи ...или не баг?
кароч кидаем на форму 2 editа и кнопку и пишем такой код unit Unit1; interface uses ...

Letter-spacing баг или не баг?
Здравствуйте! Использовал letter-spacing для увеличения расстояния между буквами. Как оказалось...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
3
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru