C++ 如何在c+中自己将double转换为char[]+;?
由于我必须非常快地将大量的double转换为char[],在进入C++ 如何在c+中自己将double转换为char[]+;?,c++,format,printf,type-conversion,double,C++,Format,Printf,Type Conversion,Double,由于我必须非常快地将大量的double转换为char[],在进入sprintf之后,我发现\u cfltcvt\u l做了真正的转换工作,在调用\u cfltcvt\u l之前,它有许多我并不真正需要的开关,案例,验证…函数,所以我想自己把double转换成char[] 我想得到与sprintf(c,“%16.9E”,d)相同的结果执行以下操作,例如: d=49.9999995;-->c={“5.000000000 E+001”} d=2.5323867855e+298;-->c={“2.532
sprintf
之后,我发现\u cfltcvt\u l
做了真正的转换工作,在调用\u cfltcvt\u l
之前,它有许多我并不真正需要的开关
,案例
,验证
…函数,所以我想自己把double转换成char[]
我想得到与sprintf(c,“%16.9E”,d)相同的结果代码>执行以下操作,例如:
d=49.9999995;-->c={“5.000000000 E+001”}
d=2.5323867855e+298;-->c={“2.532386786e+298”}
这是我的密码:
#include<iostream>
using namespace std;
void fast_sprintf(char* c, double d)
{
int i = 0, e = 0, n = 0, flag = 0;//flag=0E+;1E-
if (d < 0)
{
c[i++] = '-';
d = -d;
}
while (d >= 10)
{
d /= 10;//here is the problem
e++;
}
while (d < 1)
{
d *= 10;
e++;
flag = 1;
}
int v = d, dot;
c[i++] = '0' + v;//the integer part
dot = i;
n++;
c[i++] = '.';
d -= v;
while (d != 0 && n < 10)
{
d *= 10;
v = d;
c[i++] = '0' + v;
n++;
d -= v;
}
if (d != 0)
{
if (d * 10 >= 5)//rounding
{
int j = i - 1;
c[j]++;
while (c[j]>'9')
{
c[j] = '0';
if (j - 1 == dot)
j--;
c[--j]++;
}
}
}
else
{
while (n < 10)
{
c[i++] = '0';
n++;
}
}
c[i++] = 'E';
c[i++] = (flag == 0) ? '+' : '-';
if (e >= 100)
{
int tmp = e / 100;
c[i++] = '0' + tmp;
e -= (tmp*100);
c[i++] = '0' + e / 10;
c[i++] = '0' + e % 10;
}
else if (e <= 9)
{
c[i++] = '0';
c[i++] = '0';
c[i++] = '0' + e;
}
else
{
c[i++] = '0';
c[i++] = '0' + e / 10;
c[i++] = '0' + e % 10;
}
c[i] = '\0';
}
int main()
{
char c[20];
//double d=49.9999999995;
double d=2.5323867855e+298;
sprintf(c,"%16.9E",d);
cout<<c<<endl;
fast_sprintf(c,d);
cout<<c<<endl;
return 0;
}
d失去其精度,最后一个数字5变为4999969
那么我如何修复我的代码,或者有没有更好的方法来实现另一个sprintf(c,“%16.9E”,d)代码>
谢谢。这些转换的参考文件是&ldqou;如何
准确打印浮点数字”,由Steele和
白色它发表于PLDI'90,并可在线获取
来自ACM数字图书馆
鉴于您对速度和固定格式感兴趣,请使用
10位,一种更简单的方法可能是缩放
编号到范围[1E9…1E10)
,然后使用modf
提取
整数部分,如果分数部分为
大于0.5
。然后将整数部分转换为int
,
然后从中生成你的数字。你缩放它的数量
by应该给出指数
找到可扩展的价值可能是一个关键问题;
使用log10
是一个显而易见的解决方案,只要它在
你的图书馆。否则,你可以使用十次幂的表
(离线计算一次)和第二个表,由
指数(参见frexp
)输入此表。使用此技术,
您最多需要进行两次比较才能找到正确的缩放比例
因子。(像modf
和frexp
这样的函数通常非常有用
速度快,因为它们操纵数字的位模式
直接;如果他们不这样做,你可以通过
自己操作double
的位模式。)
当然,这只是一种方法的一般建议。
魔鬼就在细节中,要小心处理
把所有角落的箱子都弄对了,但这是一个很好的机会
它将比sprintf快,正是因为它
只有一种特定的格式。当你为所有的极端情况编写代码时,考虑到精度的损失等,你最终会得到……sprintf()
(或更糟).如果你需要精度,你肯定不能依赖浮点数:所以我想知道sprintf
是如何工作的。@PaulMcKenzie不一定。知道他瞄准的是%E
格式正好有10个数字,可以避免大量的if
s、switch
s等。其中一些可能是紧循环;知道他正好需要10个数字,事实上(不需要更多)意味着他可能完全展开循环,没有循环条件,并且他可以用整数算术完成所有事情(在int
上;传统的通用算法要求对不适合int
的值进行整数运算),
//before loop, d=2.5323867855000001e+298
while (d >= 10)
{
d /= 10;//here is the problem
e++;
}
//after loop, d=2.5323867854999969