Jak przekonwertować liczbę zmiennoprzecinkową na ciąg znaków w C ++, określając dokładność i liczbę cyfr dziesiętnych?
Na przykład: 3.14159265359 -> "3.14"
Jak przekonwertować liczbę zmiennoprzecinkową na ciąg znaków w C ++, określając dokładność i liczbę cyfr dziesiętnych?
Na przykład: 3.14159265359 -> "3.14"
Odpowiedzi:
Typowym sposobem byłoby użycie stringstream
:
#include <iomanip>
#include <sstream>
double pi = 3.14159265359;
std::stringstream stream;
stream << std::fixed << std::setprecision(2) << pi;
std::string s = stream.str();
Zobacz naprawione
Użyj stałej notacji zmiennoprzecinkowej
Ustawia
floatfield
flagę formatu dla strumienia str nafixed
.Gdy
floatfield
jest ustawiona nafixed
, wartości zmiennoprzecinkowe są zapisywane przy użyciu notacji stałoprzecinkowej: wartość jest reprezentowana przez dokładnie tyle cyfr w części dziesiętnej, ile określono w polu precyzji (precision
) i bez części wykładniczej.
i setprecision .
Do konwersji celów technicznych , takich jak przechowywanie danych w pliku XML lub JSON, C ++ 17 definiuje rodzinę funkcji to_chars .
Zakładając zgodny kompilator (którego nam brakuje w momencie pisania), można rozważyć coś takiego:
#include <array>
#include <charconv>
double pi = 3.14159265359;
std::array<char, 128> buffer;
auto [ptr, ec] = std::to_chars(buffer.data(), buffer.data() + buffer.size(), pi,
std::chars_format::fixed, 2);
if (ec == std::errc{}) {
std::string s(buffer.data(), ptr);
// ....
}
else {
// error handling
}
Zwyczajową metodą robienia tego typu rzeczy jest drukowanie na łańcuchu. W C ++ oznacza to użycie std::stringstream
czegoś takiego jak:
std::stringstream ss;
ss << std::fixed << std::setprecision(2) << number;
std::string mystring = ss.str();
snprintf
być lepiej w tym przypadku? Proszę wyjaśnić ... To na pewno nie będzie szybsze, wyprodukuje mniej kodu [Napisałem implementację printf, jest dość kompaktowa i zawiera prawie 2000 linii kodu, ale z rozszerzeniami makr dochodzi do około 2500 linii]
__printf_fp
funkcjonalności - jest raczej dziwne, że zajmuje to dużo więcej czasu stringstream
, ponieważ naprawdę nie powinno.
Możesz użyć fmt::format
funkcji z biblioteki {fmt} :
#include <fmt/core.h>
int main()
std::string s = fmt::format("{:.2f}", 3.14159265359); // s == "3.14"
}
gdzie 2
jest precyzja.
Ta funkcja formatowania została zaproponowana do standaryzacji w C ++: P0645 . Zarówno P0645, jak i {fmt} używają składni łańcucha formatu podobnej do Pythona, która jest podobna do printf
's, ale {}
zamiast tego używa jako separatorów %
.
Tutaj rozwiązanie wykorzystujące tylko standard. Należy jednak pamiętać, że to tylko zaokrągla w dół.
float number = 3.14159;
std::string num_text = std::to_string(number);
std::string rounded = num_text.substr(0, num_text.find(".")+3);
Za rounded
to daje:
3.14
Kod konwertuje cały float na łańcuch, ale wycina wszystkie znaki 2 znaki po „.”
number + 0.005
w moim przypadku.
Tutaj przedstawiam negatywny przykład, w którym chcesz uniknąć konwersji liczby zmiennoprzecinkowej na ciągi.
float num=99.463;
float tmp1=round(num*1000);
float tmp2=tmp1/1000;
cout << tmp1 << " " << tmp2 << " " << to_string(tmp2) << endl;
Dostajesz
99463 99.463 99.462997
Uwaga: zmienna num może mieć dowolną wartość bliską 99.463, otrzymasz taki sam wydruk. Chodzi o to, aby uniknąć wygodnej funkcji „to_string” w języku c ++ 11. Chwilę zajęło mi wydostanie się z tej pułapki. Najlepszym sposobem są metody stringstream i sprintf (język C). C ++ 11 lub nowszy powinien zawierać drugi parametr jako liczbę cyfr po zmiennoprzecinkowym do pokazania. W tej chwili wartością domyślną jest 6. Stawiam na to, aby inni nie tracili czasu na ten temat.
Napisałem swoją pierwszą wersję, daj mi znać, jeśli znajdziesz jakiś błąd, który należy naprawić. Możesz kontrolować dokładne zachowanie za pomocą iomanipulatora. Moja funkcja służy do wyświetlania liczby cyfr po przecinku.
string ftos(float f, int nd) {
ostringstream ostr;
int tens = stoi("1" + string(nd, '0'));
ostr << round(f*tens)/tens;
return ostr.str();
}