При разработке программного обеспечения на 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. Это уже связано с особенностями математического аппарата того компьютера, на котором производятся расчёты. Емкость разрядности чисел в любом компьютере ограничена, поэтому в самом последнем разряде после запятой происходит округление, которое вызывает появление подобных вариантов числа. Это необходимо учитывать при точных расчётах.
Добрый день, подскажите пожалуйста. Столкнулся с проблемой, парсю JSON получаю цифровые значения типа string, пример (QJsonValue(string, "0.0000000001")), делаю преобразование типа в double.
На выходе у меня получается такое значение 1Е-10, каким образом мне получить значение 0.0000000001 в переменной double. Делать дополнительное преобразование в QML считаю не нормальным.
Решение было найдено. В QML использовал метод JavaScript toFixed() Method, массив data_1[0].toFixed(10), 10 количество мне нужных знаков после запятой.