просчет с плавающей запятой, когда переменная int32_t делится на 10
я хочу спросить, как получить правильное значение float из uint32_t или переменная long делится на 10??
long var3 = 1139399025;
int a = 3;
int b = 10;
void setup() {
Serial.begin(9600);
Serial.println((float)a/b,2);
Serial.println((float)var3/b,2);
}
void loop() {
}
результат
0.3
113939904.00
выдает 113939904.00 вместо 113939902.50, пожалуйста, как это исправить?
@mukhlas, 👍1
Обсуждение1 ответ
1139399025 не является числом с плавающей запятой: наибольшее нечетное целое число,
может быть точно представлен как float
224 − 1 = 16777215. Тогда, когда var3
равно
приведено к float
, оно округляется до ближайшего числа с плавающей запятой, что
это 1139399040. Это совсем небольшая ошибка, особенно учитывая
что в этом диапазоне только кратные 128 могут быть точно
представлены в виде чисел с плавающей запятой.
Деление 1139399040 на 10 дает 113939904, что является числом с плавающей запятой. Деление с плавающей запятой дает точный результат, который печатается. Действительно, операции с плавающей запятой не всегда дают неточные результаты: иногда они точны. Однако, если вы не знаете, что вы делаете, точные результаты случаются только по счастливой случайности. В общем, ожидайте каждой операции с плавающей запятой, чтобы сделать относительную ошибку округления в диапазон 10−7.
Настоятельно рекомендуется прочитать: О чем должен знать каждый программист Арифметика с плавающей запятой.
ОБНОВЛЕНИЕ: если вы хотите напечатать значение целого числа, деленного на 10, вы можете разделить число, используя евклидово деление. Распечатать частное, затем десятичная точка, затем остаток:
Serial.print(var3 / 10); // частное
Serial.print('.');
Serial.println(var3 % 10); // остаток
Поскольку это все целочисленные операции, ошибка округления отсутствует. вовлеченный. Очевидно, что этот трюк не работает для произвольных делителей.
Так что я должен делать?, @mukhlas
@mukhlas: не используйте поплавки., @Edgar Bonet
@mukhlas Или используйте double
, который дает более значащие цифры, для этого конкретного случая. Но в любом случае вам нужно понимать плавающую точку, как предложил Эдгар., @the busybee
@thebusybee: микроконтроллеры AVR (точнее, их порт GCC) не поддерживают числа с двойной точностью: их тип double
реализован как float32, точно так же, как float
., @Edgar Bonet
Да неужели? Ну тогда не повезло. :-(, @the busybee
Спасибо вам всем :), @mukhlas
- Преобразование Float в int не работает прямо в методе с использованием varargs
- Преобразование из Float в Int дает странные результаты. Что я делаю не так?
- Как использовать данные float с датчика с помощью библиотеки Arduino mouse library
- Float печатается только 2 десятичных знака после запятой
- Отправка и получение различных типов данных через I2C в Arduino
- Как преобразовать строку в массив байтов
- Как перевести float в четыре байта?
- Проблемы с преобразованием byte[] в String
каково значение var3, когда оно преобразуется в число с плавающей запятой?, @jsotola
длинная переменная3 = 1139399025;, @mukhlas
Поплавки имеют только ограниченную точность, см. https://cdn.arduino.cc/reference/en/language/variables/data-types/float/. Вы получаете лучшую точность, используя двойник, но только на 32-битном Arduino (Due и т. Д.). Однако некоторая потеря точности все равно будет., @6v6gt
Я использую ардуино мега 2560, @mukhlas
Отвечает ли это на ваш вопрос? [Серийный номер, числа, отправленные как с плавающей запятой, и символы отличаются на уровне 1e-8](https://arduinoprosto.ru/q/8872/serial-numbers-sent-as-floating-point-and-characters-are -различный-на-1e-8-уровневом), @the busybee