Como você converte um float em uma string em C ++ enquanto especifica a precisão e o número de dígitos decimais?
Por exemplo: 3.14159265359 -> "3.14"
c++
string
floating-point
Shannon Matthews
fonte
fonte
Respostas:
Uma maneira típica seria 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();
Veja corrigido
e definir precisão .
Para conversões de propósito técnico , como armazenamento de dados em arquivo XML ou JSON, C ++ 17 define a família to_chars de funções.
Supondo um compilador compatível (que não possuíamos no momento da escrita), algo como isto pode ser considerado:
#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 }
fonte
O método usual para fazer esse tipo de coisa é "imprimir em string". Em C ++, isso significa usar
std::stringstream
algo como:std::stringstream ss; ss << std::fixed << std::setprecision(2) << number; std::string mystring = ss.str();
fonte
Outra opção é
snprintf
:double pi = 3.1415926; std::string s(16, '\0'); auto written = std::snprintf(&s[0], s.size(), "%.2f", pi); s.resize(written);
Demo . O tratamento de erros deve ser adicionado, ou seja, verificação de
written < 0
.fonte
snprintf
seria melhor neste caso? Por favor, explique ... Certamente não será mais rápido, produzirá menos código [eu escrevi uma implementação de printf, é bastante compacto em pouco menos de 2.000 linhas de código, mas com expansões de macro chega a cerca de 2500 linhas]__printf_fp
funcionalidade subjacente - é bastante estranho que demore muito mais tempostringstream
, porque realmente não deveria.Você pode usar a
fmt::format
função da biblioteca {fmt} :#include <fmt/core.h> int main() std::string s = fmt::format("{:.2f}", 3.14159265359); // s == "3.14" }
onde
2
está uma precisão.Este recurso de formatação foi proposto para padronização em C ++: P0645 . Ambos P0645 e {fmt} usam uma sintaxe de string de formato semelhante a Python que é semelhante a de
printf
, mas usa{}
como delimitadores em vez de%
.fonte
Aqui, uma solução usando apenas std. No entanto, observe que isso apenas arredonda para baixo.
float number = 3.14159; std::string num_text = std::to_string(number); std::string rounded = num_text.substr(0, num_text.find(".")+3);
Para
rounded
isso rende:3.14
O código converte todo o float em string, mas corta todos os caracteres 2 caracteres após o "."
fonte
number + 0.005
no meu caso.Aqui estou fornecendo um exemplo negativo onde você deseja evitar ao converter números flutuantes em strings.
float num=99.463; float tmp1=round(num*1000); float tmp2=tmp1/1000; cout << tmp1 << " " << tmp2 << " " << to_string(tmp2) << endl;
Você consegue
99463 99.463 99.462997
Nota: a variável num pode ser qualquer valor próximo a 99,463, você obterá a mesma impressão. O objetivo é evitar a conveniente função c ++ 11 "to_string". Levei um tempo para sair dessa armadilha. A melhor maneira são os métodos stringstream e sprintf (linguagem C). C ++ 11 ou mais recente deve fornecer um segundo parâmetro como o número de dígitos após o ponto flutuante a ser mostrado. No momento, o padrão é 6. Estou postulando isso para que outros não percam tempo com esse assunto.
Eu escrevi minha primeira versão, por favor, deixe-me saber se você encontrar algum bug que precise ser corrigido. Você pode controlar o comportamento exato com o iomanipulator. Minha função é mostrar o número de dígitos após o ponto decimal.
string ftos(float f, int nd) { ostringstream ostr; int tens = stoi("1" + string(nd, '0')); ostr << round(f*tens)/tens; return ostr.str(); }
fonte