Comment convertir un flottant en chaîne en C ++ tout en spécifiant la précision et le nombre de chiffres décimaux?
Par exemple: 3.14159265359 -> "3.14"
Comment convertir un flottant en chaîne en C ++ tout en spécifiant la précision et le nombre de chiffres décimaux?
Par exemple: 3.14159265359 -> "3.14"
Réponses:
Une manière typique serait d'utiliser stringstream
:
#include <iomanip>
#include <sstream>
double pi = 3.14159265359;
std::stringstream stream;
stream << std::fixed << std::setprecision(2) << pi;
std::string s = stream.str();
Voir fixe
Utiliser la notation à virgule flottante fixe
Définit le
floatfield
indicateur de format pour le flux strfixed
.Lorsque
floatfield
est défini surfixed
, les valeurs à virgule flottante sont écrites en utilisant la notation à virgule fixe: la valeur est représentée avec exactement autant de chiffres dans la partie décimale que spécifié par le champ de précision (precision
) et sans partie d'exposant.
et définir la précision .
Pour conversions à des fins techniques , comme le stockage de données dans un fichier XML ou JSON, C ++ 17 définit la famille de fonctions to_chars .
En supposant un compilateur conforme (qui nous manque au moment de la rédaction), quelque chose comme ça peut être envisagé:
#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
}
La méthode habituelle pour faire ce genre de chose est d '«imprimer dans une chaîne». En C ++, cela signifie utiliser std::stringstream
quelque chose comme:
std::stringstream ss;
ss << std::fixed << std::setprecision(2) << number;
std::string mystring = ss.str();
snprintf
mieux dans ce cas? Veuillez expliquer ... Ce ne sera certainement pas plus rapide, produisez moins de code [J'ai écrit une implémentation printf, c'est assez compact avec un peu moins de 2000 lignes de code, mais avec des extensions de macro, cela atteint environ 2500 lignes]
__printf_fp
fonctionnalités sous-jacentes - il est plutôt étrange que cela prenne tellement plus de temps stringstream
, car cela ne devrait vraiment pas avoir à le faire.
Vous pouvez utiliser la fmt::format
fonction de la bibliothèque {fmt} :
#include <fmt/core.h>
int main()
std::string s = fmt::format("{:.2f}", 3.14159265359); // s == "3.14"
}
où 2
est une précision.
Cette fonction de formatage a été proposée pour la normalisation en C ++: P0645 . P0645 et {fmt} utilisent tous deux une syntaxe de chaîne de format semblable à Python qui est similaire à celle de printf
's mais qui utilise {}
comme délimiteurs au lieu de %
.
Voici une solution utilisant uniquement std. Cependant, notez que cela arrondit seulement vers le bas.
float number = 3.14159;
std::string num_text = std::to_string(number);
std::string rounded = num_text.substr(0, num_text.find(".")+3);
Car rounded
cela donne:
3.14
Le code convertit tout le flottant en chaîne, mais coupe tous les caractères 2 caractères après le "."
number + 0.005
dans mon cas.
Ici, je donne un exemple négatif où vous voulez éviter lors de la conversion de nombres flottants en chaînes.
float num=99.463;
float tmp1=round(num*1000);
float tmp2=tmp1/1000;
cout << tmp1 << " " << tmp2 << " " << to_string(tmp2) << endl;
Vous obtenez
99463 99.463 99.462997
Remarque: la variable num peut être n'importe quelle valeur proche de 99,463, vous obtiendrez la même impression. Le but est d'éviter la fonction pratique "to_string" de c ++ 11. Il m'a fallu un certain temps pour sortir ce piège. Le meilleur moyen est les méthodes stringstream et sprintf (langage C). C ++ 11 ou plus récent doit fournir un deuxième paramètre comme nombre de chiffres après la virgule flottante à afficher. Pour le moment, la valeur par défaut est 6. Je pose ceci pour que d'autres ne perdent pas de temps sur ce sujet.
J'ai écrit ma première version, faites-le moi savoir si vous trouvez un bogue qui doit être corrigé. Vous pouvez contrôler le comportement exact avec l'iomanipulator. Ma fonction est d'afficher le nombre de chiffres après la virgule décimale.
string ftos(float f, int nd) {
ostringstream ostr;
int tens = stoi("1" + string(nd, '0'));
ostr << round(f*tens)/tens;
return ostr.str();
}