C++ 如何在c+中自己将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

由于我必须非常快地将大量的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.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