Ошибка преобразования float в int

Я пытаюсь преобразовать 1,06 в 106, умножив на 100, но ответ приходит 105, я не знаю, почему. Переменная ver может быть любой десятичной в этом формате x.xx

float ver = 1.06;
int vers = ver * 100;
vm[0] = (vers / 100U) % 10;
vm[1] = (vers / 10U) % 10;
vm[2] = (vers / 1U) % 10;
Serial.println(vers);  

Не могли бы вы сообщить мне, что я делаю не так, или, может быть, я должен сделать что-то еще.

, 👍1


1 ответ


Лучший ответ:

5

1.06 не является плавающей точкой. Ближайший float составляет 1.059999942779541015625. Если вы умножите это на 100, вы получите число, которое, опять же, не является плавающим. Округление до ближайшего значения с плавающей точкой дает 105,99999237060546875, что является результатом выражения ver * 100и всего на один ULP меньше 106. Да, вычисления с плавающей запятой довольно часто включают в себя этапы округления.

Приведение к int неявно округляется до нуля, и вы получаете 105, что является правильным результатом. Правильно в соответствии с правилами арифметики IEEE 754.

Возможно, вам захочется округлить() до ближайшего целого числа перед приведением.

Переменная ver может быть любой десятичной в этом формате x.xx

Нет, значение с плавающей запятой не может быть “любым десятичным” в этом формате. Float хранятся в двоичном формате, и большинство десятичных чисел (чисел, которые могут быть записаны с конечным числом десятичных цифр) не могут быть записаны в двоичном формате с конечным числом битов.

За исключением нескольких значений (а именно кратных 0,25), ver может хранить только приближение десятичного числа.

,

Спасибо за ответ, теперь это имеет смысл., @Shahreza