gpt4 book ai didi

c++ - 如何在 C++ 中自己将 double 转换为 char[]?

转载 作者:太空狗 更新时间:2023-10-29 23:15:35 25 4
gpt4 key购买 nike

因为我必须非常快速地将大量 double 转换为 char[],在进入 sprintf 之后,我发现 _cfltcvt_l 完成了真正的转换工作,并且在 _cfltcvt_l 被调用,它有很多switch,case,validate...我并不真正需要的功能,所以我想自己将 double 转换为 char[]。

我想得到与 sprintf(c,"%16.9E",d); 相同的结果,例如:

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);

谢谢。

最佳答案

这些转换的引用文档是 &ldqou;How to准确打印 float ”,Steele 和白色的;它发表于 PLDI '90,可在线获取来自 ACM 数字图书馆。

鉴于您对速度和固定格式感兴趣,10 位数,一种更简单的方法可能是缩放number 到 [1E9...1E10) 范围内,然后使用 modf 提取整数部分,如果小数部分是递增的大于 0.5。然后将整数部分转换为一个int,并从中生成你的数字。你缩放的数量by 应该给出指数。

找到扩展它的值(value)可能是一个关键问题;使用 log10 是一个显而易见的解决方案,前提是它是准确的你的图书馆。否则,您可以使用 10 的幂表(计算一次,离线),以及第二个表,由指数(参见 frexp)到这个表中。使用这种技术,您最多需要进行两次比较才能找到正确的缩放比例因素。 (像 modffrexp 这样的函数通常非常快,因为他们操纵数字的位模式直接地;如果他们不这样做,很容易做你需要的自己操作 double 的位模式。)

当然,这只是一种方法的一般性建议。细节决定成败,需要多加注意正确处理所有极端情况。但有一个很好的机会它会比 sprintf 更快,正是因为它使用一种特定格式。

关于c++ - 如何在 C++ 中自己将 double 转换为 char[]?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28429513/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com