Преобразовать string во float на ардуино
Я пытаюсь преобразовать строку в float, но у меня возникают проблемы с точностью, даже с собственным примером строки Arduino я получаю плохие результаты.
Пример 0: Входная строка: 1.234567 После преобразования в float: 1.2345669
Пример 1: Входная строка: 60.123456 После преобразования в float: 60.1234512
Пример 2: Входная строка: 9.876543 После преобразования в float:9.8765430
Почему это происходит и как мне от этого избавиться?
@user3635319, 👍3
4 ответа
Если вы используете atof() для преобразования строки в число с плавающей запятой, вы получите только 6 или 7 цифр точности. И числа в ваших примерах уже обладают такой высокой точностью.
Вы понимаете это, потому что float использует определенное количество байтов (у меня нет под рукой Arduino), я думаю, что это 4 байта.
В этих байтах может быть сохранена только определенная точность, поэтому наименьшие значащие цифры округляются (двоичные, в результате чего получаются разные конечные цифры).
Только для, например, Arduino Due: Вместо этого вы можете использовать двойные, см. https://www.arduino.cc/reference/en/language/variables/data-types/double/
Вы можете проверить наличие функции strtod
, но я не уверен, что она обрабатывается Arduino:
https://www.techonthenet.com/c_language/standard_library_functions/stdlib_h/strtod.php
Если это не сработает, вы можете использовать функцию для разделения". " и обработки левой/правой части, чтобы преобразовать ее в unsigned long и объединить ее вместе. Но если будут задействованы экспоненциальные и минусовые знаки, это может стать сложнее.
Здесь речь идет о двух проблемах:
1 – Ограниченная точность типа данных float
Float имеет точность примерно 10-7, и любое число, которое
не является точным float, должно быть округлено до ближайшего float.
Например, два float, ближайшие к 1.234567, являются
10356298 × 2-23 = 1,2345669269561767578125 и
10356299 × 2−23 = 1.23456704616546630859375.
Последнее ближе всего.
2 – Наивная строка для реализации с плавающей точкой в ядре Arduino
Ядро Arduino нацелено на то, чтобы быть небольшим и потреблять мало ресурсов. Иногда он срезает углы, ценой точности. В этом случае, хотя правильная реализация должна округлять 1.234567 вверх, поскольку ближайшее значение с плавающей точкой выше этого числа, фактическая реализация завершается округлением в меньшую сторону. Таким образом, вы получаете примерно 1.234566927, что меньше на 0,61 ULPs (единицы последнего места), вместо ожидаемой ошибки 0,39 ULPs.
- Программа arduino выдаёт ошибку expected //primary-expression before ')' token error: //expected ';' before '}' token E
- Использование StringStream в скетче Arduino
- Чтение строки, разделенной запятыми
- Преобразование числа с плавающей запятой в шестнадцатеричное значение
- Округление числа с плавающей запятой
- Как объединить строки и текст вместе?
- Хранение значений широты и долготы в виде символов с заданной точностью
- Оптимизированный генератор случайных буквенно-цифровых строк
Float-это 32 бита. На платах AVR
double
- это просто синонимfloat
., @Edgar Bonet@EdgarBonet Спасибо за это замечание, я обновил свой ответ (только для Arduino Due)., @Michel Keijzers