Синтаксический анализ Arduino Double неверен
У меня проблемы с анализом GPS-координат с помощью Arduino ide.
Честно говоря, я хочу обрабатывать данные без библиотеки.
От моего датчика я получаю эту строку: 4815.98450
Результат String.toDouble(): 4815.9843750
Я также разобрал его самостоятельно, но получил тот же результат: (да, этот код нехороший ;))
char buf[10];
msg.toCharArray(buf, 19);
double num = 0.0;
int c;
c = buf[0] - '0';
double num0 = (c * 1000);
c = buf[1] - '0';
double num1 = (c * 100);
c = buf[2] - '0';
double num2 = (c * 10);
c = buf[3] - '0';
double num3 = (c * 1);
c = buf[5] - '0';
double num5 = (c * 0.1);
c = buf[6] - '0';
double num6 = (c * 0.01);
c = buf[7] - '0';
double num7 = (c * 0.001);
c = buf[8] - '0';
double num8 = (c * 0.0001);
c = buf[9] - '0';
double num9 = (c * 0.00001);
num = num + num0;
num = num + num1;
num = num + num2;
num = num + num3;
num = num + num5;
num = num + num6;
num = num + num7;
num = num + num8;
num = num + num9;
Есть ли у кого-нибудь решение моей проблемы?
Большое спасибо :=)
@Benjamin_Ellmer, 👍1
3 ответа
Лучший ответ:
Нет простого решения. Используемый вами Arduino не поддерживает
с плавающей запятой двойной точности. Тип double
— это просто псевдоним для
float
с 24-битной точностью.
На самом деле ваша программа выдает правильный результат, так как число с плавающей запятой ближайшим к 4815,98450 является именно 4815,984375.
double
(или float) — это просто неподходящий тип данных.
Возможно, вы принимаете int(4815) и float(0,98450) как два числа?
Кстати, могу поспорить, что ваш сенсор не получит объект String.
Я читаю вывод из TX моего датчика, поэтому я почти уверен, что это строка ;) я понял, что могу выполнить расчет без первых двух цифр числа. есть случаи, когда это не работает, но такие случаи очень маловероятны, @Benjamin_Ellmer
Вы можете преобразовать это в длинное, выполнить арифметические действия и преобразовать его обратно в десятичное число ASCII:
Удалить десятичную точку из строки. Преобразуйте оставшуюся строку цифр в длинную. Теперь у вас есть координата в двоичном формате, в единицах младшей значащей десятичной цифры; 1 младший бит == 0,00001, если вы использовали 5 знаков после запятой.
Управляйте своими данными, как вам нужно, используя арифметику длинных целых чисел.
Разделите значение на 10^ - (количество цифр дроби, которые вы использовали). Частное - это целая часть числа; остаток - дробная часть. Выведите частное и десятичную точку. Распечатайте оставшееся заполнение нулями слева по мере необходимости, чтобы в результате напечатать (количество цифр дроби, которое вы использовали) общее количество цифр дроби.
Преобразование вывода становится еще проще, если вы хотите использовать sprintf():
Разделите значение на 10^ - (количество использованных цифр дроби), как указано выше. Предположим, 5 мест, как в вашем примере:
char buffer[BIGENOUGH+1];
sprintf(buffer, "%ld.%05ld", value/100000, value%100000);
Обратите внимание, что я сделал два деления, чтобы получить частное и остаток, и предположил, что вы можете допустить падение производительности. Если вы ожидаете получить много значений, а скорость является фактором, вы можете найти или написать процедуру деления, которая может возвращать как частное, так и остаток от одного деления.
Обновление: @edgar_bonet отмечает, что компилятор достаточно умен, чтобы заметить, что этот фрагмент использует оба результата численного деления и в конце концов избегает двойного деления.
Относительно «_подпрограммы, которая может возвращать как частное, так и остаток от одного деления_»: это именно то, что делает avr-gcc при компиляции приведенного вами примера., @Edgar Bonet
- C++ против языка Arduino?
- avrdude ser_open() can't set com-state
- Как читать и записывать EEPROM в ESP8266
- Float печатается только 2 десятичных знака после запятой
- устаревшее преобразование из строковой константы в 'char*'
- Запрограммировать ATMega328P и использовать его без платы Arduino.
- Разница между print() и println()
- Как исправить: Invalid conversion from 'const char*' to 'char*' [-fpermissive]
Спасибо за ваш ответ! Вы мне очень помогли, потому что теперь я знаю, что это не ошибка. Но теперь я ищу обходной путь :), @Benjamin_Ellmer
@Benjamin_Ellmer: Может быть, хранить целые и дробные части отдельно?, @Edgar Bonet