读《C程序设计语言》笔记11
发现字符串处理真是太多了,之前写了字符串转整型,整型转字符串,今天要字符串转浮点数;
题目要求:
写一个字符串转浮点数的函数,使它可以处理形如:123.45e-6的科学表示法,其中,浮点数后面可能会紧跟一个e或E以及一个指数(可能有正负号)。
#include <stdio.h>
#include <ctype.h>
double strtofloat(char s[])
{
double val, power;
int exp, i, sign;
for(i=0; isspace(s[i]); i++) //skip white space
;
sign=(s[i]=='-') ? -1 : 1;
if(s[i]=='+' || s[i]=='-')
i++;
for(val=0.0; isdigit(s[i]); i++)
val=10.0*val + (s[i]-'0');
if(s[i]='.')
i++;
for(power=1.0; isdigit(s[i]); i++)
{
val=10.0*val + (s[i]-'0');
power*=10.0;
}
val= sign*val/power;
if(s[i]=='e' || s[i]=='E')
{
sign=(s[++i]=='-') ? -1 : 1;
if(s[i]=='+' || s[i]=='-')
i++;
for(exp=0; isdigit(s[i]); i++)
exp= 10*exp + (s[i]-'0');
if(sign==1)
while(exp-- >0) //positive exponent
val*=10;
else
while(exp-- >0) //negative exponent
val/=10;
}
return val;
}
int main()
{
char s[]="123.45e3";
printf("%0.2f\n",strtofloat(s));
system("pause");
return 0;
}
执行结果如下:

结果保留了小数点后两位,函数的前半部分可以处理一般的字符串,形如"123.54",加上后半部分就可以处理科学表示法的了。
在处理科学表示法,e为负的情况下,val要除以10.
为什么呢?用val去除以10而不是用val去乘以0.1的原因是:0.1无法用二进制数精确地表示出来,这就是著名的浮点数精度问题。比如表示***.4,除去前面的整数,我们直接看后面的小数部分:0.4=0.5*0+0.25*1+0.125*1+0.0625*0+……,貌似永远算不完啊,实际直到加上前面的整数部分算够53位就行了。隐藏位技术:最高位的1不写入内存(最终保留下来的还是52位)。
在大多数机器上,0.1的二进制表示法都要比0.1稍微小一点,用10.0乘以0.1并不能精确地得到1.0。从结果上看,虽然两种做法都会有一定的误差,但连续地“除以10”要比连续地“乘以0.1”更精确。
浙公网安备 33010602011771号