¿Cómo se convierte un flotante en una cadena en C ++ mientras se especifica la precisión y el número de dígitos decimales?
Por ejemplo: 3.14159265359 -> "3.14"
c++
string
floating-point
Shannon Matthews
fuente
fuente
Respuestas:
Una forma típica sería usar
stringstream
:#include <iomanip> #include <sstream> double pi = 3.14159265359; std::stringstream stream; stream << std::fixed << std::setprecision(2) << pi; std::string s = stream.str();
Ver fijo
y setprecision .
Para conversiones de propósito técnico , como almacenar datos en archivos XML o JSON, C ++ 17 define la familia de funciones to_chars .
Suponiendo un compilador compatible (que carecemos en el momento de escribir este artículo), se puede considerar algo como esto:
#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 }
fuente
El método habitual para hacer este tipo de cosas es "imprimir en una cadena". En C ++ eso significa usar
std::stringstream
algo como:std::stringstream ss; ss << std::fixed << std::setprecision(2) << number; std::string mystring = ss.str();
fuente
Otra opcion es
snprintf
:double pi = 3.1415926; std::string s(16, '\0'); auto written = std::snprintf(&s[0], s.size(), "%.2f", pi); s.resize(written);
Demo . Se debe agregar el manejo de errores, es decir, verificar
written < 0
.fuente
snprintf
mejor en este caso? Por favor explique ... Ciertamente no será más rápido, producirá menos código [He escrito una implementación de printf, es bastante compacta con poco menos de 2000 líneas de código, pero con macro expansiones llega a alrededor de 2500 líneas]__printf_fp
funcionalidad subyacente , es bastante extraño que demore mucho más tiempostringstream
, ya que realmente no debería hacerlo.Puede usar la
fmt::format
función de la biblioteca {fmt} :#include <fmt/core.h> int main() std::string s = fmt::format("{:.2f}", 3.14159265359); // s == "3.14" }
donde
2
es una precisión.Esta función de formato se ha propuesto para la estandarización en C ++: P0645 . Tanto P0645 como {fmt} usan una sintaxis de cadena de formato similar a Python que es similar a
printf
's pero usa{}
como delimitadores en lugar de%
.fuente
Aquí una solución que usa solo std. Sin embargo, tenga en cuenta que esto solo se redondea a la baja.
float number = 3.14159; std::string num_text = std::to_string(number); std::string rounded = num_text.substr(0, num_text.find(".")+3);
Porque
rounded
rinde:3.14
El código convierte todo el flotante en una cadena, pero corta todos los caracteres 2 caracteres después del "."
fuente
number + 0.005
en mi caso.Aquí proporciono un ejemplo negativo en el que desea evitar al convertir un número flotante en cadenas.
float num=99.463; float tmp1=round(num*1000); float tmp2=tmp1/1000; cout << tmp1 << " " << tmp2 << " " << to_string(tmp2) << endl;
Usted obtiene
99463 99.463 99.462997
Nota: la variable num puede ser cualquier valor cercano a 99.463, obtendrá la misma impresión. El punto es evitar la conveniente función de c ++ 11 "to_string". Me tomó un tiempo salir de esta trampa. La mejor forma son los métodos stringstream y sprintf (lenguaje C). C ++ 11 o posterior debe proporcionar un segundo parámetro como el número de dígitos después del punto flotante para mostrar. En este momento, el valor predeterminado es 6. Estoy planteando esto para que otros no pierdan el tiempo en este tema.
Escribí mi primera versión, avíseme si encuentra algún error que deba solucionarse. Puede controlar el comportamiento exacto con el iomanipulador. Mi función es para mostrar el número de dígitos después del punto decimal.
string ftos(float f, int nd) { ostringstream ostr; int tens = stoi("1" + string(nd, '0')); ostr << round(f*tens)/tens; return ostr.str(); }
fuente