读《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”更精确。

posted on 2011-07-16 23:36  Tony.Works  阅读(543)  评论(0编辑  收藏  举报