Wie man Double in String in benutzerfreundlicher Form umwandelt

Wie man Double in String in benutzerfreundlicher Form umwandelt


ich habe folgendes Problem:
Kunde möchte double präsentieren geben Sie eine string ein auf optimale Weise. Es muss in eine Zeichenfolge konvertiert und auf einem Formular (SMS, Tabelle und andere) angezeigt werden.


100000000.949999 needs to be converted in 100000000.950;
10.000000001 -> 10.0;
100000000000000.19292 -> 1e+14;
1000.123456789 -> 1000.123;
0.00001 -> 0.0;

Der Code zum Konvertieren ist performancekritisch, das bedeutet, dass kein std::stringstream + setprecision() verwendet werden.


Es wird großartig sein, params 'precision' als Argument meiner toStringNew() zu implementieren funktionieren, aber diese Verbesserungen können unser gesamtes System kritisch beeinflussen, und wir planen, sie in der nächsten Version zu implementieren.
Aber dieses Problem ist jetzt aktuell.

Ich habe folgenden Code geschrieben:


inline bool toStringNew(std::string& str, double const& value)
{
static const char *zero_double_str = "0.0";
static const double zero_double_limit = 0.001;
static const int max_double_prec_symbol = 13;
static const int max_fract_num = 3;
static const int max_fract_mul = pow(10, max_fract_num);
str.clear();
//get digits of integer part
double fabs_value = fabs(value);
int64_t len = log10(fabs_value);
//Round 2 zero
if(len <= 0) //it means that only fraction part is present
{
if(fabs_value < zero_double_limit)
{
str = zero_double_str;
return true;
}
//use default
return boost::spirit::karma::generate(std::back_inserter(str), value);
}
else if(len > max_double_prec_symbol) //default
{
return boost::spirit::karma::generate(std::back_inserter(str), value);
}
//cast to integer
int64_t i = static_cast<int64_t>(value);
//cast fract to integer
int64_t fract_i = static_cast<int64_t>(round((value - i)* max_fract_mul));
//reserve string memory
size_t str_len = len + 1 + max_fract_num + (value > 0 ? 0 : 1) + 1;
str.reserve(str_len);
//convert integer
boost::spirit::karma::generate(std::back_inserter(str), i);
str+='.';
//convert fract
if(fract_i > 0)
{
str+='.';
int64_t fract_i_len = log10(fract_i);
//fill zero before: 0.001 -> 1 -> 001
while(++fract_i_len < max_fract_num)
{
str += '0';
}
//remove zero after: 010 -> 01
while(!(fract_i % 10))
{
fract_i = fract_i / 10;
}
boost::spirit::karma::generate(std::back_inserter(str), fract_i);
}
boost::spirit::karma::generate(std::back_inserter(str), fract_i);
return true;
}

Dies funktioniert 1,5 mal schneller als boost::spirit::karma::generate() für double Typ.


Können Sie mir Ratschläge geben, wie ich meinen Kunden zufriedenstellen kann?


Einige Code-Antworten


100000000.949999 needs to be converted in 100000000.950;
10.000000001 ->
10.0;
100000000000000.19292 ->
1e+14;
1000.123456789 ->
1000.123;
0.00001 ->
0.0;
inline bool toStringNew(std::string&
str, double const&
value) {
static const char *zero_double_str = "0.0";
static const double zero_double_limit = 0.001;
static const int max_double_prec_symbol = 13;
static const int max_fract_num = 3;
static const int max_fract_mul = pow(10, max_fract_num);
str.clear();
//get digits of integer part
double fabs_value = fabs(value);
int64_t len = log10(fabs_value);
//Round 2 zero
if(len <= 0) //it means that only fraction part is present
{
if(fabs_value <
zero_double_limit)
{ str = zero_double_str;
return true;
}
//use default
return boost::spirit::karma::generate(std::back_inserter(str), value);
}
else if(len >
max_double_prec_symbol) //default
{
return boost::spirit::karma::generate(std::back_inserter(str), value);
}
//cast to integer
int64_t i = static_cast<int64_t>(value);
//cast fract to integer
int64_t fract_i = static_cast<int64_t>(round((value - i)* max_fract_mul));
//reserve string memory
size_t str_len = len + 1 + max_fract_num + (value >
0 ? 0 : 1) + 1;
str.reserve(str_len);
//convert integer
boost::spirit::karma::generate(std::back_inserter(str), i);
str+='.';
//convert fract
if(fract_i >
0)
{
str+='.';
int64_t fract_i_len = log10(fract_i);
//fill zero before: 0.001 ->
1 ->
001
while(++fract_i_len <
max_fract_num)
{ str += '0';
}
//remove zero after: 010 ->
01
while(!(fract_i % 10))
{ fract_i = fract_i / 10;
}
boost::spirit::karma::generate(std::back_inserter(str), fract_i);
}
boost::spirit::karma::generate(std::back_inserter(str), fract_i);
return true;
}
#include <cmath>
#include <strtk.hpp>
#include <iostream>
using namespace std;
int main ( int argc, char **argv ) { double pi = M_PI;
std::cout <<
strtk::type_to_string<double>( pi ) <<
std::endl;
return 0;
}