Преобразовать string во float на ардуино

Я пытаюсь преобразовать строку в float, но у меня возникают проблемы с точностью, даже с собственным примером строки Arduino я получаю плохие результаты.

Пример 0: Входная строка: 1.234567 После преобразования в float: 1.2345669

Пример 1: Входная строка: 60.123456 После преобразования в float: 60.1234512

Пример 2: Входная строка: 9.876543 После преобразования в float:9.8765430

Почему это происходит и как мне от этого избавиться?

, 👍3


4 ответа


0

Похоже, что сначала я должен преобразовать в строку, а затем использовать atof.

,

0

Если вы используете atof() для преобразования строки в число с плавающей запятой, вы получите только 6 или 7 цифр точности. И числа в ваших примерах уже обладают такой высокой точностью.

,

2

Вы понимаете это, потому что 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 и объединить ее вместе. Но если будут задействованы экспоненциальные и минусовые знаки, это может стать сложнее.

,

Float-это 32 бита. На платах AVR double - это просто синоним float., @Edgar Bonet

@EdgarBonet Спасибо за это замечание, я обновил свой ответ (только для Arduino Due)., @Michel Keijzers


1

Здесь речь идет о двух проблемах:

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.

,