C 将双精度/浮点转换为字符串

C 将双精度/浮点转换为字符串,c,string,floating-point,C,String,Floating Point,我需要将浮点数转换为十进制(或其他基数)的等效字符串。首先需要以xE+0格式进行转换,其中x是浮点数 我的想法是先将浮点数截断成一个临时整数,然后将该整数转换成字符串,然后考虑小数部分,乘以 10 < /代码>,而小数部分不会成为 0 < /C>。小数部分转移到小数点左侧后,再次应用整数到字符串函数,并将小数部分转换为字符串。有没有比这更快的更好的方法?这种方法会引起任何副作用吗 若要将浮点数转换为指数表示,我是否应执行与上述相同的操作,然后调整幂?或者直接对浮点表示进行位掩码,并将每个部分转换

我需要将浮点数转换为十进制(或其他基数)的等效字符串。首先需要以
xE+0
格式进行转换,其中
x
是浮点数

我的想法是先将浮点数截断成一个临时整数,然后将该整数转换成字符串,然后考虑小数部分,乘以<代码> 10 < /代码>,而小数部分不会成为<代码> 0 < /C>。小数部分转移到小数点左侧后,再次应用整数到字符串函数,并将小数部分转换为字符串。有没有比这更快的更好的方法?这种方法会引起任何副作用吗

若要将浮点数转换为指数表示,我是否应执行与上述相同的操作,然后调整幂?或者直接对浮点表示进行位掩码,并将每个部分转换为字符串


注意:不能使用其他函数,因为我绝对不能访问任何库函数。这段代码进入一个玩具内核。

去看看一些C库中使用
%f
printf()
实现。

看看BSD C标准库是否有fcvt()。您可以从它的源代码开始,而不是从头开始编写代码。UNIX 98标准fcvt()显然不输出科学记数法,因此您必须自己实现它,但我认为这并不难。

唯一精确的解决方案是对基转换执行任意精度的十进制算法,由于精确值可以是非常长-对于80位
长双精度
,最多约10000位小数位。幸运的是,对于IEEE
double
,它“仅”达到大约700个位置

与其使用单个十进制数字,不如使用基数10亿(适用于32位整数的10的最高幂),然后在计算结束时将这些“基数10亿”数字转换为9个十进制数字

在LGPL MIT许可下,我有一个非常密集(相当难理解)但高效的实现:

如果去掉所有十六进制浮点支持、无穷大/nan支持、
%g
/
%f
/
%e
变体支持、舍入(如果您只需要精确的答案,就永远不需要舍入)和其他您可能不需要的东西,那么剩下的代码相当简单。

使用
stdlib.h
中的
snprintf()
。为我工作

double num = 123412341234.123456789; 
char output[50];

snprintf(output, 50, "%f", num);

printf("%s", output);

我知道这可能是不必要的,但我制作了一个将float转换为string的函数:

代码:
#包括
/**伯爵号**/
整数n_tu(整数,整数计数)
{
int结果=1;
同时(计数-->0)
结果*=数字;
返回结果;
}
/***将浮点转换为字符串***/
void float_to_字符串(float f,char r[])
{
长整数长度,长度2,i,数字,位置,符号;
浮点数2;
符号=-1;/-1==正数
if(f<0)
{
符号='-';
f*=-1;
}
数字2=f;
数字=f;
长度=0;//小数部分的大小
长度2=0;//第十个的大小
/*计算长度的十分之二*/
而((number2-(float)number)!=0.0&&!((number2-(float)number)<0.0))
{
数字2=f*(n_-tu(10.0,长度2+1));
数字=数字2;
长度2++;
}
/*计算长度小数部分*/
对于(长度=(f>1)?0:1;f>1;长度++)
f/=10;
位置=长度;
长度=长度+1+长度2;
数字=数字2;
如果(符号=='-')
{
长度++;
位置++;
}
对于(i=长度;i>=0;i--)
{
如果(i==(长度))
r[i]='\0';
否则如果(i==(位置))
r[i]=';
else if(符号='-'&&i==0)
r[i]='-';
其他的
{
r[i]=(数字%10)+“0”;
数目/=10;
}
}
}
使用以下方法:

void double_to_char(double f,char * buffer){
    gcvt(f,10,buffer);
}
sprintf可以做到这一点:

#include <stdio.h>
int main() {
  float w = 234.567;
  char x[__SIZEOF_FLOAT__];
  sprintf(x, "%g", w);
  puts(x);
}
#包括
int main(){
浮子w=234.567;
字符x[_;u大小f__;u浮点数];
sprintf(x,“%g”,w);
看跌期权(x);
}

或者,您可以使用C99输出格式,即:
[-]0x1.p
,对于双精度数字,偏差为
0x3ff
。这也是序列化的首选格式,因为它是精确的,不依赖于浮点环境的当前设置(如舍入或将非规范化刷新为零)。有点普通,但可能仍然有用,而且速度非常快。

我祈祷人们能尝试回答这个问题,而不是问“为什么不能使用库函数?”。需要实现一个基本库作为起点可能会有所帮助。整个尾数是“小数部分”。IEEE 754标准化浮点数是一个小数部分(“1.”是隐式的)。您考虑的方法会丢掉精度,并且有很差的舍入误差。你需要多高的精确度?固定数量的地方?当读回十进制表示时,是否足以重现双精度的准确值?确切的数值?你是说我先把它转换成2^32个基数,然后再从中得到10个基数字符串?代码中的一点注释和/或一个简短的描述将真正有助于深入代码。@phoxis:您对
fmt\u fp
感兴趣
y
是输出到
f
的数字
w
=字符串宽度,
p
=精度,
fl
=标志,
t
=类型。格式代码
%20.5g
提供了
w=20,p=5,fl=0,t='g'
w=0,p=-1
提供了默认格式)。提取所需的部分应该是可行的。(注意,我只是简单地看了一下源代码,但它看起来相当可靠,对于我链接的快速而脏的部分出现故障的情况,它可以正常工作)@phoxis:让你开始的东西:
#include <stdio.h>
int main() {
  float w = 234.567;
  char x[__SIZEOF_FLOAT__];
  sprintf(x, "%g", w);
  puts(x);
}