求double浮点数转字符串算法

haierpro 2010-09-07 10:55:59
求double浮点数转字符串算法,不能用sprintf等系统转换函数.
...全文
573 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
xianyuxiaoqiang 2010-09-10
  • 打赏
  • 举报
回复
CSDN说我回复中存在非法字符!,无语,只好放到博客里:
double浮点数转字符串算法,不用sprintf等系统转换函数.
shi3590 2010-09-09
  • 打赏
  • 举报
回复
随手瞎写了个玩玩。

#define MAX_PRECISION 16
#define MAX_LENGTH 50
char *dtoa(double d)
{
double t=d;
int qty=0;
int i=0;
int flag=0;
int max=0;
char *tmp=new char[MAX_LENGTH];
if (d<0.0)
{
tmp[i++]='-';
t*=-1;
}
while (t>1.0)
{
t/=10;
max=++qty;
flag=1;
}
while (qty>max-MAX_PRECISION)
{
if (qty==0&&flag==0)
{
tmp[i++]='0';
tmp[i++]='.';
}
tmp[i++]=(char)(floor(t*10)+48);
t=t*10-floor(t*10);
if (--qty==0&&qty!=max-MAX_PRECISION)
{
tmp[i++]='.';
}
if (qty==max-MAX_PRECISION&&t>0.5)
{
if (tmp[i-1]>='0'&&tmp[i-1]<'9') tmp[i-1]+=1;
}
}
tmp[i]=0x00;
return tmp;
}

void main()
{
double a=-12345123.5530089365;
cout.precision(MAX_PRECISION);
cout<<a<<endl;
cout<<dtoa(a)<<endl;
}
dhfsa_maxwit 2010-09-09
  • 打赏
  • 举报
回复
MaxWit技术讨论区http://linux.chinaunix.net/bbs/forum-70-1.html
taodm 2010-09-09
  • 打赏
  • 举报
回复
不能用printf,你难道还不能找个printf的源码抄抄?VC啊、gcc啊、BCB啊都提供了printf的源码的。
suchx 2010-09-09
  • 打赏
  • 举报
回复

if(exponent>=0) //use >= instead of >
{ s[i++]='+';
}
suchx 2010-09-09
  • 打赏
  • 举报
回复

#include "stdafx.h"
#include "math.h"
const int Accuracy=14;
const int signsize=1;
const int expsize=3;
const int FloatSize=signsize+2+Accuracy+2+expsize+1;

int _tmain(int argc, _TCHAR* argv[])
{ double x=0.0,y;
int exponent=0,i,j,c,temp;
char sign='+';
char s[FloatSize]={0};
printf("Input x : ");
scanf_s("%lf",&x);
if(x<0.0)
{ sign='-';
}
y=fabs(x);
if(y>1.0)
{ while(y>10.0)
{ y=y/10.0;
exponent++;
}
}
else if(y==1.0)
{
}
else
{ do
{ y=y*10.0;
exponent--;
}while(y<1.0);
}
//printf("%c%fe%d\n",sign,y,exponent);
i=0;
if(sign=='-')
{ s[i++]='-';
}
s[i++]=int(y)+'0';
y=y-(double)(s[i-1]-'0');
s[i++]='.';
j=i;
for(;i<Accuracy+j;i++)
{ y=y*10;
s[i]=int(y)+'0';
y=y-(double)(s[i]-'0');
}
y=y*10.0;
if(int(y)>=5)
{ c=1;
j=i-1;
while(c)
{ temp=s[j]-'0'+c;
c=temp/10;
s[j]=temp-10;
j--;
}
}
s[i++]='e';
if(exponent>0)
{ s[i++]='+';
}
else
{ s[i++]='-';
exponent=-exponent;
}
j=100;
while(exponent>0)
{ s[i++]=exponent/j+'0';
exponent=exponent%j;
j=j/10;
}
s[i]='\0';
printf("x=%s\n",s);
printf("x=%.14le\n",x);
//printf("x=%.14lf\n",x);
return 0;
}
suchx 2010-09-09
  • 打赏
  • 举报
回复

#include "stdafx.h"
#include "math.h"
const int Accuracy=6;
const int signsize=1;
const int expsize=3;
const int FloatSize=signsize+2+Accuracy+2+expsize+1;

int _tmain(int argc, _TCHAR* argv[])
{ float x=0.0,y;
int exponent=0,i,j;
char sign='+';
char s[FloatSize]={0};
printf("Input x : ");
scanf_s("%f",&x);
if(x<0.0)
{ sign='-';
}
y=fabs(x);
if(y>1.0)
{ while(y>10.0)
{ y=y/10;
exponent++;
}
}
else if(y==1.0)
{
}
else
{ do
{ y=y*10;
exponent--;
}while(y<1.0);
}
//printf("%c%fe%d\n",sign,y,exponent);
i=0;
if(sign=='-')
{ s[i++]='-';
}
s[i++]=int(y)+'0';
y=y-(float)(s[i-1]-'0');
s[i++]='.';
j=i;
for(;i<Accuracy+j;i++)
{ y=y*10;
s[i]=int(y)+'0';
y=y-(float)(s[i]-'0');
}
y=y*10;
if(int(y)>=5)
{ s[i-1]++;
}
s[i++]='e';
if(exponent>0)
{ s[i++]='+';
}
else
{ s[i++]='-';
exponent=-exponent;
}
j=100;
while(exponent>0)
{ s[i++]=exponent/j+'0';
exponent=exponent%j;
j=j/10;
}
s[i]='\0';
printf("x=%s\n",s);
printf("x=%e\n",x);
printf("x=%f\n",x);
return 0;
}

You can change x to double and accuracy to maybe 15. I compare the result with the printf, it seems like that the result are same.
arong1234 2010-09-07
  • 打赏
  • 举报
回复
知道格式就没有所谓的算法了,按照格式解码即可。如果你还问所谓的算法,说明你还没懂格式和原理。64位的double可以保证15位精度,所以不是问题。[Quote=引用 6 楼 haierpro 的回复:]
引用 4 楼 hairetz 的回复:
你的意思是不能使用任何系统的库,就是自己实现?

那就得按ieee浮点数去解析了。

http://dev.csdn.net/htmls/28/28201.html

这个GG花了很大功夫整理,楼主好好看看。


谢谢,原理都明白,我需要的是具体的算法,特别是对于指数比较大的,至少要保证13位的精度。
[/Quote]
luoqi 2010-09-07
  • 打赏
  • 举报
回复
double a=15.1273;
int f=10000;//精度
int b=a;
int c=(a-b)*f;
char buf[32]={0};
sprintf(buf,"%d.%d",b,c);

//注意,intel编译器,精度会少0.00000000001
湛卢VV 2010-09-07
  • 打赏
  • 举报
回复
看看系统函数的原型不就知道了么?
三岁、就很帅 2010-09-07
  • 打赏
  • 举报
回复
函数名: ecvt
功 能: 把一个浮点数转换为字符串
用 法: char ecvt(double value, int ndigit, int *decpt, int *sign);
程序例:

#include <stdlib.h>
#include <stdio.h>
#include <conio.h>

int main(void)
{
char *string;
double value;
int dec, sign;
int ndig = 10;

clrscr();
value = 9.876;
string = ecvt(value, ndig, &dec, &sign);
printf("string = %s dec = %d \
sign = %d\n", string, dec, sign);

value = -123.45;
ndig= 15;
string = ecvt(value,ndig,&dec,&sign);
printf("string = %s dec = %d sign = %d\n",
string, dec, sign);


value = 0.6789e5; /* scientific
notation */
ndig = 5;
string = ecvt(value,ndig,&dec,&sign);
printf("string = %s dec = %d\
sign = %d\n", string, dec, sign);

return 0;
}
haierpro 2010-09-07
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 hairetz 的回复:]
你的意思是不能使用任何系统的库,就是自己实现?

那就得按ieee浮点数去解析了。

http://dev.csdn.net/htmls/28/28201.html

这个GG花了很大功夫整理,楼主好好看看。
[/Quote]

谢谢,原理都明白,我需要的是具体的算法,特别是对于指数比较大的,至少要保证13位的精度。
arong1234 2010-09-07
  • 打赏
  • 举报
回复
这个精度不可能好的,乘以10就是一个不精确的计算。楼主需要看明白IEEE浮点数格式,根据那个来进行处理[Quote=引用 3 楼 problc 的回复:]
看要求精度了,
double a;
int b;
double c;
b = (int)a;
c = a - b;
整数部分int 好转吧
小数部分c每次乘10转整数部分。
[/Quote]
  • 打赏
  • 举报
回复
你的意思是不能使用任何系统的库,就是自己实现?

那就得按ieee浮点数去解析了。

http://dev.csdn.net/htmls/28/28201.html

这个GG花了很大功夫整理,楼主好好看看。

problc 2010-09-07
  • 打赏
  • 举报
回复
看要求精度了,
double a;
int b;
double c;
b = (int)a;
c = a - b;
整数部分int 好转吧
小数部分c每次乘10转整数部分。
老邓 2010-09-07
  • 打赏
  • 举报
回复
haierpro 2010-09-07
  • 打赏
  • 举报
回复
自己先顶下
haierpro 2010-09-07
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 arong1234 的回复:]
另外:如果你sprintf不用,寻找其他系统函数没有任何意义,因为sprintf就是一个系统函数,做的正是你要的东西。如果你找系统函数,要找的是什么系统函数呢?
[/Quote]

是用于嵌入式系统的,很多嵌入式系统的sprintf都不支持浮点数的格式化输出。如果能用sprintf我就不用废这神了。
haierpro 2010-09-07
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 arong1234 的回复:]
我想进制转换是基础的基础,不知道你这个不会,不过学过计算机原理的都该知道

引用 11 楼 haierpro 的回复:
8楼的老大,系统函数的原型我找了很久了,就是没找到,请问你能给个吗?
10楼的大哥,知道格式是一回事,显示算法是另外一回事好不好。知道的是二进制的指数格式,你知道怎么转换成10进制的指数吗?比如3x2^1000,请问等于 ?x10^? 别给我计算个数字就完事,我要的是字符……
[/Quote]

这个。。。请你拿出你的基础的基础去实际动手写一下这个函数,你就会明白了,记住了,不能调用任何系统函数。
saishow 2010-09-07
  • 打赏
  • 举报
回复
strtod
语法:

#include <cstdlib>
double strtod( const char *start, char **end );strtod() 返回遇到的start中开始的双精度浮点数。end被设置为指向start在双精度浮点数之后留下的部分。如果发生溢出,strtod() 返回 HUGE_VAL 或者 -HUGE_VAL。

楼主参见一下这个.看看过程自己做一个就可以了.
加载更多回复(3)

69,369

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧