Преобразование строки в плавающую и форматирование

В настоящее время у меня есть что-то вроде этого

float a = SomeQString.toFloat(); //QString has 2.37

Теперь число с плавающей запятой равно 2,3690000031..

Я хочу 2.3700000000 .. любое предложение о том, как я могу это сделать? Также почему я получаю 2,369 вместо 2,37?


person MistyD    schedule 31.08.2013    source источник
comment
@MitchWheat: Округление - это именно то, почему результат НЕ 2,370000. Оно округляется до ближайшего представимого значения float.   -  person MSalters    schedule 31.08.2013


Ответы (2)


(Столько раз спрашивали и объясняли.) Невозможно получить 2.37 в float. Невозможно получить 2.37 в double. Невозможно получить 2.37 ни в каком двоичном формате с плавающей запятой в стиле IEEE-754. 2.37 не представляется точно в таких двоичных форматах с плавающей запятой.

Прочитайте что должен знать каждый специалист по информатике об арифметике с плавающей запятой

Один из жизнеспособных способов «получить» 2.37 – это сохранить 2.369... в float (что вы уже делаете), а затем округлить его до 2.37 в то время, когда вам нужно будет сгенерировать десятичное представление, т. е. в то время, когда вы должны представить/вывести значение пользователю.

person AnT    schedule 31.08.2013
comment
Я согласен. Округление числа с плавающей запятой является математическим. - person Abhineet; 31.08.2013
comment
Я не хочу получать 2,37, я хочу 2,3700000, преобразование искажает мои значения. Также спасибо за перефразировку вашего ответа. - person MistyD; 31.08.2013
comment
@MistyD: Обратите внимание, что это будет не 2.370000. Это будет 2.370000358... или что-то в этом роде. И вполне возможно, что этот 2.369... ближе к вашему исходному 2.37, чем другой альтернативный 2.370000358.... Вот почему был выбран 2.369.... Это имеет смысл на самом деле. - person AnT; 31.08.2013
comment
2.37f, float ближе всего к 2,37, это точно 2.36999988555908203125. Следующее число с плавающей запятой после этого — 2.3700001239776611328125. Если OP не удовлетворяет ни одно из этих значений, OP должен использовать другой тип, чем float. - person Pascal Cuoq; 31.08.2013
comment
@Pascal Cuoq: по-видимому, алгоритм преобразования toFloat теряет некоторую точность (неудивительно). Обратите внимание, что это по-прежнему 2.36999..., а не 2.370000..., ожидаемое OP. - person AnT; 31.08.2013
comment
Хм, я не понимаю этот ответ. Мой фрагмент работает нормально. Может ли кто-нибудь помочь мне с этим, чего мне не хватает? - person lpapp; 31.08.2013
comment
@PascalCuoq: вероятно, проблема с двойным ударом. 2.370 преобразуется в число с плавающей запятой, затем преобразуется обратно в строку с использованием неправильного округления до "2.369", затем обратно в число с плавающей запятой, где оно становится 2.3690000358... - person 6502; 31.08.2013
comment
@Laszlo Papp: Ваш фрагмент делает именно то, что предлагается в ответе. Он создает неточное значение в float (не 2.37), а затем округляет его до ожидаемого представления (2.37) во время вывода. Так уж получилось, что точность вывода по умолчанию округлена до 2.37. Если вы увеличите точность вывода, вы увидите, что на самом деле это не 2.37. - person AnT; 31.08.2013

Если вы настаиваете на использовании Qt, этот код вам подходит:

#include <QString>
#include <QTextStream>
#include <QDebug>

using namespace std;

int main()
{
    QString floatString = "2.37";
    QTextStream floatTextStream(&floatString);
    float f;
    floatTextStream >> f;
    qDebug() << f;

    return 0;
} 

Запустите следующую команду, например, с помощью gcc и Qt 5 (или что-то подобное, если у вас другой сценарий):

Команда: g++ -I/usr/include/qt -I/usr/include/qt/QtCore -lQt5Core -fPIC main.cpp && ./a.out

Выход: 2.37

Однако для этого вам не нужен QString. См. приведенный ниже код, который генерирует выходные данные 2.37, как и ожидалось.

#include <string>
#include <sstream>
#include <iostream>

using namespace std;

int main()
{
    string floatString = "2.37";
    istringstream floatStringStream(floatString);
    float f;
    floatStringStream >> f;
    cout << f;

    return 0;
}

Запустите следующую команду, например, с помощью gcc (или что-то подобное, если у вас другой сценарий):

Команда: g++ main.cpp && ./a.out

Выход: 2.37

person lpapp    schedule 31.08.2013