Bagaimana Anda mengonversi pelampung menjadi string di C ++ sambil menentukan presisi & jumlah digit desimal?
Sebagai contoh: 3.14159265359 -> "3.14"
Bagaimana Anda mengonversi pelampung menjadi string di C ++ sambil menentukan presisi & jumlah digit desimal?
Sebagai contoh: 3.14159265359 -> "3.14"
Jawaban:
Cara tipikal adalah dengan menggunakan stringstream
:
#include <iomanip>
#include <sstream>
double pi = 3.14159265359;
std::stringstream stream;
stream << std::fixed << std::setprecision(2) << pi;
std::string s = stream.str();
Lihat diperbaiki
Gunakan notasi floating-point tetap
Setel
floatfield
bendera format untuk aliran strfixed
.Jika
floatfield
disetel kefixed
, nilai floating-point ditulis menggunakan notasi titik tetap: nilai diwakili dengan angka persis sama di bagian desimal seperti yang ditentukan oleh bidang presisi (precision
) dan tanpa bagian eksponen.
dan setprecision .
Untuk konversi tujuan teknis , seperti menyimpan data dalam file XML atau JSON, C ++ 17 mendefinisikan keluarga fungsi to_chars .
Dengan asumsi kompiler yang sesuai (yang tidak kami miliki pada saat penulisan), hal seperti ini dapat dipertimbangkan:
#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
}
Metode umum untuk melakukan hal semacam ini adalah dengan "mencetak ke string". Dalam C ++ itu berarti menggunakan std::stringstream
sesuatu seperti:
std::stringstream ss;
ss << std::fixed << std::setprecision(2) << number;
std::string mystring = ss.str();
snprintf
lebih baik dalam kasus ini? Tolong jelaskan ... Ini pasti tidak akan lebih cepat, menghasilkan lebih sedikit kode [Saya telah menulis implementasi printf, itu cukup kompak hanya di bawah 2000 baris kode, tetapi dengan ekspansi makro mencapai sekitar 2500 baris]
__printf_fp
fungsionalitas dasar yang sama - agak aneh bahwa proses ini memakan waktu lebih lama stringstream
, karena seharusnya tidak perlu.
Anda bisa menggunakan C ++ 20 std::format
atau fmt::format
fungsi dari pustaka {fmt} , std::format
berdasarkan:
#include <fmt/core.h>
int main()
std::string s = fmt::format("{:.2f}", 3.14159265359); // s == "3.14"
}
dimana 2
presisi.
Di sini solusi hanya menggunakan std. Namun, perhatikan bahwa ini hanya membulatkan ke bawah.
float number = 3.14159;
std::string num_text = std::to_string(number);
std::string rounded = num_text.substr(0, num_text.find(".")+3);
Untuk rounded
itu menghasilkan:
3.14
Kode tersebut mengubah seluruh float menjadi string, tetapi memotong semua karakter 2 karakter setelah "."
number + 0.005
dalam kasus saya.
Di sini saya memberikan contoh negatif di mana Anda ingin menghindari saat mengubah bilangan mengambang menjadi string.
float num=99.463;
float tmp1=round(num*1000);
float tmp2=tmp1/1000;
cout << tmp1 << " " << tmp2 << " " << to_string(tmp2) << endl;
Anda mendapatkan
99463 99.463 99.462997
Catatan: variabel num dapat berupa nilai apa pun yang mendekati 99,463, Anda akan mendapatkan hasil cetak yang sama. Intinya adalah untuk menghindari fungsi "to_string" c ++ 11 yang nyaman. Butuh beberapa saat untuk keluar dari jebakan ini. Cara terbaik adalah metode stringstream dan sprintf (bahasa C). C ++ 11 atau yang lebih baru harus memberikan parameter kedua sebagai jumlah digit setelah titik mengambang untuk ditampilkan. Saat ini defaultnya adalah 6. Saya mengemukakan hal ini agar orang lain tidak membuang waktu untuk masalah ini.
Saya menulis versi pertama saya, beri tahu saya jika Anda menemukan bug yang perlu diperbaiki. Anda dapat mengontrol perilaku persisnya dengan iomanipulator. Fungsi saya adalah untuk menunjukkan jumlah digit setelah koma desimal.
string ftos(float f, int nd) {
ostringstream ostr;
int tens = stoi("1" + string(nd, '0'));
ostr << round(f*tens)/tens;
return ostr.str();
}