Реклама

Qt/C++ - Урок 057. Ошибки вывода qDebug() для чисел с плавающей точкой

TutorialQtQt, qDebug, float706

При разработке программного обеспечения на Qt довелось столкнуться с одним нюансом при выводе чисел с плавающей запятой через qDebug(). Проблема заключается в том, что выводятся не все символы после запятой. Тем же самым грешит и вывод std::cout .

Подобный user case может возникнуть в следующей ситуации:

У вас имеется объект QString, который содержит некое число "8564.26495574", которое мы переводим в число с плавающей точкой с помощью метода toDouble(), и проверяем результат с помощью вывода qDebug() , но вот незадача, вывода оказывается ложным.

QString str("8564.26495574");
qDebug() << str.toDouble();

// В выводе получаем -> 8564.26

Хотя на самом деле мы получаем совершенно правильное число, то есть из строки было получено число 8564.26495574 , просто вывод qDebug() показывает округлённый результат.

Тоже самое можно наблюдать, если попытаться просто вывести значение числа double в qDebug().

double a = 8564.26495574;
qDebug() << a;

// В выводе получаем -> 8564.26

Убедиться в том, что никаких ошибок не происходит при конвертировании числа из QString в double можно, воспользовавшись переменной bool, указатель на которую передаётся в качестве аргумента в метод toDouble().

QString str("8564.26495574");
bool ok = false;
qDebug() << str.toDouble(&ok);
qDebug() << ok;

// В выводе получим следующее
// 8564.26
// true - то есть ошибок не было

Для того, чтобы сделать корректный вывод, необходимо воспользоваться методом QString::arg() с указанием типа форматирования и точности.

QString str("8564.26495574");

double a = 8564.26495574;
double b = str.toDouble();

qDebug() << QString("%1").arg(a, 0, 'f', 5);
qDebug() << QString("%1").arg(a, 0, 'g', 5);
qDebug() << QString("%1").arg(a, 0, 'e', 10);
qDebug() << QString("%1").arg(a, 0, 'g', 30);

qDebug() << QString("%1").arg(b, 0, 'f', 5);
qDebug() << QString("%1").arg(b, 0, 'g', 5);
qDebug() << QString("%1").arg(b, 0, 'e', 10);
qDebug() << QString("%1").arg(b, 0, 'g', 30);

В результате получим следующий вывод qDebug():

"8564.26496"
"8564.3"
"8.5642649557e+3"
"8564.26495574000000488013029099"

"8564.26496"
"8564.3"
"8.5642649557e+3"
"8564.26495574000000488013029099"

В обоих случаях получаем идентичный результат, поскольку и там и там число одно и то же.

Пару слов о типах форматирования:

  • 'g' - выводит указанное количество символов начиная с самого большого разряда в целой части числа;
  • 'f' - выводит указанное количество символов с точностью после запятой;
  • 'e' - выводит указанное количество символов с точностью после запятой и указанием числа скрытых разрядов.

Как видите в выводе есть небольшая погрешность 8564.26495574000000488013029099. Это уже связано с особенностями математического аппарата того компьютера, на котором производятся расчёты. Емкость разрядности чисел в любом компьютере ограничена, поэтому в самом последнем разряде после запятой происходит округление, которое вызывает появление подобных вариантов числа. Это необходимо учитывать при точных расчётах.

@

Реклама

Реклама

Комментарии

Комментарии

Только авторизованные пользователи могут оставлять комментарии.
Пожалуйста, Авторизуйтесь или Зарегистрируйтесь

Реклама

Реклама