Ondalık basamakların hassasiyetini ve sayısını belirtirken bir kayan noktayı C ++ 'da bir dizeye nasıl dönüştürebilirsiniz?
Örneğin: 3.14159265359 -> "3.14"
Ondalık basamakların hassasiyetini ve sayısını belirtirken bir kayan noktayı C ++ 'da bir dizeye nasıl dönüştürebilirsiniz?
Örneğin: 3.14159265359 -> "3.14"
Yanıtlar:
Tipik bir yol stringstream
şunları kullanmaktır :
#include <iomanip>
#include <sstream>
double pi = 3.14159265359;
std::stringstream stream;
stream << std::fixed << std::setprecision(2) << pi;
std::string s = stream.str();
Düzeltildi gör
Sabit kayan nokta gösterimi kullan
Str akışı için
floatfield
biçim bayrağını olarak ayarlar .fixed
Olarak
floatfield
ayarlandığındafixed
, kayan nokta değerleri sabit nokta notasyonu kullanılarak yazılır: değer, ondalık kısımda tam olarak kesinlik alanı (precision
) tarafından belirtildiği gibi çok sayıda basamakla temsil edilir ve üs parçası olmadan temsil edilir.
ve setprecision .
Verileri XML veya JSON dosyasında depolamak gibi teknik amaçlı dönüşümler için , C ++ 17, to_chars işlev ailesini tanımlar .
Uyumlu bir derleyici varsayarsak (yazarken eksik olduğumuz), şöyle bir şey düşünülebilir:
#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
}
Bu tür şeyleri yapmanın alışılmış yöntemi "dizeye yazdırmaktır". C ++ 'da bu, aşağıdaki std::stringstream
gibi bir şey kullanmak anlamına gelir :
std::stringstream ss;
ss << std::fixed << std::setprecision(2) << number;
std::string mystring = ss.str();
snprintf
Bu durumda neden daha iyi olur ? Lütfen açıklayın ... Kesinlikle daha hızlı olmayacak, daha az kod üretecek [Bir printf uygulaması yazdım, 2000 satır kodun hemen altında oldukça kompakt, ancak makro genişletmelerle yaklaşık 2500 satıra
__printf_fp
işlevselliği kullanıyor - stringstream
gerçekten gerekmemesi gerektiği için çok daha uzun sürmesi oldukça garip .
Sen C ++ 20 kullanabilir std::format
veya fmt::format
gelen işlevi {Fmt} kütüphanede , std::format
dayanmaktadır:
#include <fmt/core.h>
int main()
std::string s = fmt::format("{:.2f}", 3.14159265359); // s == "3.14"
}
2
kesinlik nerede .
Burada sadece std kullanan bir çözüm. Ancak, bunun yalnızca aşağı yuvarlandığını unutmayın.
float number = 3.14159;
std::string num_text = std::to_string(number);
std::string rounded = num_text.substr(0, num_text.find(".")+3);
İçin rounded
beraber, burada:
3.14
Kod, tüm şamandırayı dizeye dönüştürür, ancak "." Karakterinden sonra tüm karakterleri 2 karakter keser.
number + 0.005
benim durumumda.
Burada, kayan sayıyı dizelere dönüştürürken kaçınmak istediğiniz olumsuz bir örnek veriyorum.
float num=99.463;
float tmp1=round(num*1000);
float tmp2=tmp1/1000;
cout << tmp1 << " " << tmp2 << " " << to_string(tmp2) << endl;
Sen alırsın
99463 99.463 99.462997
Not: num değişkeni 99.463'e yakın herhangi bir değer olabilir, aynı çıktıyı alacaksınız. Buradaki amaç, uygun c ++ 11 "to_string" işlevinden kaçınmaktır. Bu tuzaktan kurtulmam biraz zaman aldı. En iyi yol stringstream ve sprintf yöntemleridir (C dili). C ++ 11 veya daha yenisi, gösterilecek kayan noktadan sonraki basamak sayısı olarak ikinci bir parametre sağlamalıdır. Şu anda varsayılan değer 6'dır. Başkalarının bu konu üzerinde zaman kaybetmemesi için bunu varsayıyorum.
İlk sürümümü yazdım, düzeltilmesi gereken herhangi bir hata bulursanız lütfen bana bildirin. İomanipulator ile tam davranışı kontrol edebilirsiniz. Benim işlevim, ondalık noktadan sonraki basamakların sayısını göstermek içindir.
string ftos(float f, int nd) {
ostringstream ostr;
int tens = stoi("1" + string(nd, '0'));
ostr << round(f*tens)/tens;
return ostr.str();
}