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"
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"
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
Use notação de ponto flutuante fixo
Define o
floatfieldsinalizador de formato para o str streamfixed.Quando
floatfieldé definido comofixed, os valores de ponto flutuante são escritos usando notação de ponto fixo: o valor é representado com exatamente tantos dígitos na parte decimal como especificado pelo campo de precisão (precision) e sem parte expoente.
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
}
O método usual para fazer esse tipo de coisa é "imprimir em string". Em C ++, isso significa usar std::stringstreamalgo como:
std::stringstream ss;
ss << std::fixed << std::setprecision(2) << number;
std::string mystring = ss.str();
snprintfseria 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_fpfuncionalidade subjacente - é bastante estranho que demore muito mais tempo stringstream, porque realmente não deveria.
Você pode usar a fmt::formatfunção da biblioteca {fmt} :
#include <fmt/core.h>
int main()
std::string s = fmt::format("{:.2f}", 3.14159265359); // s == "3.14"
}
onde 2está 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 %.
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 roundedisso rende:
3.14
O código converte todo o float em string, mas corta todos os caracteres 2 caracteres após o "."
number + 0.005no 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();
}