【发布时间】:2015-04-10 08:35:24
【问题描述】:
由于我必须非常快地将大量的 double 转换为 char[],在进入 sprintf 之后,我发现 _cfltcvt_l 完成了真正的转换工作,而在调用 _cfltcvt_l 之前,它有很多 @987654329 @,case,validate...函数我真的不需要,所以我想自己将double转换为char[]。
我想得到和sprintf(c,"%16.9E",d);does一样的结果,例如:
d=49.9999999995; --> c={"5.000000000E+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=2.5323867855e+298 时,c={"2.532386785e+298"} 而不是 c={"2.532386786e+298"}
那是因为在这个循环之后:
//before loop, d=2.5323867855000001e+298
while (d >= 10)
{
d /= 10;//here is the problem
e++;
}
//after loop, d=2.5323867854999969
d 失去精度,最后一位 5 变为 4999969。
那么我该如何修复我的代码,或者有更好的方法来实现另一个sprintf(c,"%16.9E",d);?
谢谢。
【问题讨论】:
-
当您为所有极端情况编写代码、处理精度损失等问题时,您最终会得到...
sprintf()(或更糟)。 -
如果你需要精度,你绝对不能依赖浮点数:docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
-
所以我想知道
sprintf是如何工作的。 -
@PaulMcKenzie 不一定。知道他的目标是
"%E格式,正好是 10 位数字,可以避免很多ifs、switchs 等。其中一些可能处于紧密循环中;知道他需要正好 10 位数字,实际上(仅此而已)意味着他可能完全展开循环,没有循环条件,并且他可以用整数算术做所有事情(在int上;通用算法传统上需要对不适合int) 的值进行整数运算。
标签: c++ format printf type-conversion double