如何以用户友好的形式将"双精度"转换为"字符串"
How to convert 'double' to 'string' in user-friendly form
我有以下问题:客户希望以最优的方式将double
型呈现给string
型。它需要转换为字符串,并显示在一个窗体(sms,表和其他)。
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;
转换代码是一个性能关键,这意味着不应该使用std::stringstream
+ setprecision()
。
实现参数'precision'作为我的toStringNew()
函数的参数是很棒的,但是这个改进可能会严重影响我们所有的系统,我们计划在下一个版本中实现它。但这个问题现在是现实的。
我写了下面的代码:
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;
}
对于double
类型,此工作速度比boost::spirit::karma::generate()
快1.5倍。
我会看看c++ String Toolkit Library。我已经用它来解析和数字转换,它已经显示出非常快。
#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;
}
如果性能很重要,可以使用snprintf。它会比你自己的解决方案更好,而且我认为它会表现得更好。使用*
格式说明符,您还可以将精度作为参数。
相关文章:
- 为什么将双精度转换为 int 似乎在第 16 位数字之后将其四舍五入?
- 在 c++ 中从双精度转换为字符串
- 使用 sprintf 和 %g 将双精度转换为字符串的意外结果
- 从双精度转换为整数的显式类型是否始终检查整数溢出?
- C++,遇到将双精度转换为整数的问题
- 在C++中将双精度转换为intptr_t
- 将大双精度转换为科学记数法以用作字符串?
- 了解双精度转换与整数转换中的整数与截断关系
- 将 OLE 自动化日期 (OADate) 双精度转换为结构 tm,而不使用 VariantTime到SystemTime
- 无法在赋值中将"双精度 (*)[4]"转换为"双精度**"
- 将大双精度转换为无符号 int 期间堆栈损坏
- 将双精度转换为本地8位
- 警告从"双精度"转换为"int"
- 如何将双精度转换为浮点指针
- 将双精度转换为整数时出错
- 使用并集将双精度转换为十六进制再转换为双精度
- 是否有可以将每个双精度转换为唯一uint64_t,保持精度和顺序的功能?(为什么我找不到?
- 使用定点表示法将双精度转换为字符串,没有尾随零和机智的冲刺
- 在C++中将双精度转换为字符*/字符串
- 无法将双精度 [] [] 转换为双精度 **