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