atof函数,可以处理科学计数法

     源自《The C Programming Language》P62 pr4-2,代码位于ex4.2中:

     对atof函数进行扩充,使它能够处理形如:123.45e-6的科学表示法,其中浮点数后面可能会紧跟一个e或E以及一个指数

   代码:

ContractedBlock.gif ExpandedBlockStart.gif main.c
 
    
1 #include < stdio.h >
2 #include < ctype.h >
3
4 #define MAXLINE 100
5
6 int getLine( char s[], int lim);
7 double atof( char s[]);
8 int pow( int base , int expn);
9
10 int main()
11 {
12
13 char line[MAXLINE];
14 int len;
15 while ((len = getLine(line, MAXLINE)) > 0 )
16 printf( " %f\n " , atof(line));
17 // printf("the size of double: %d\n", sizeof(double));
18 // printf("the size of float: %d\n", sizeof(float));
19
20 return 0 ;
21 }
22
23 int getLine( char s[], int lim) // 从终端获取一行字符
24 {
25
26 int i;
27 int c;
28
29 for (i = 0 ; -- lim > 0 && (c = getchar()) != EOF && c != ' \n ' ; ++ i)
30 s[i] = c;
31 if (c == ' \n ' )
32 s[i ++ ] = c;
33 s[i] = ' \0 ' ;
34
35 return i;
36
37 }
38
39 int pow( int base , int expn) // 底数为base,指数为expn的指数求值
40 {
41
42 int i;
43 int sum;
44
45 sum = 1 ;
46 for (i = 0 ; i < expn; ++ i)
47 sum = sum * base ;
48
49 return sum;
50
51 }
52
53 double atof( char s[]) // 将字符串s转换成double型的浮点数
54 {
55
56 int i;
57 int sign;
58 int flag;
59 int expn;
60 double val;
61 double power;
62
63 sign = 1 ;
64 flag = 0 ;
65 power = 1.0 ;
66 expn = 0 ;
67 for (i = 0 ; isspace(s[i]); ++ i)
68 ;
69 if (s[i] == ' - ' )
70 sign = - 1 ;
71 if (s[i] == ' + ' || s[i] == ' - ' )
72 ++ i;
73 for (val = 0.0 ; isdigit(s[i]); ++ i)
74 val = val * 10.0 + (s[i] - ' 0 ' );
75 if (s[i] == ' . ' )
76 ++ i;
77 for (; isdigit(s[i]); ++ i)
78 {
79 val = val * 10.0 + (s[i] - ' 0 ' );
80 // power = power * 10.0;
81 ++ flag;
82 }
83 if (s[i] == ' e ' || s[i] == ' E ' ) // 如果写成s[i++] == 'e' || s[i++] == 'E',if(s[i] == '-')
84 // 则当输入的字符串带有E时,不能正确得到结果,这是因为在一
85 // 个语句中使用两次自增操作,引起歧义
86 if (s[ ++ i] == ' - ' )
87 {
88 ++ i;
89 for (; isdigit(s[i]); ++ i)
90 expn = expn * 10 + (s[i] - ' 0 ' );
91 expn = expn + flag;
92 power = pow( 10 , expn);
93 return sign * val / power;
94 }
95 else
96 {
97 for (; isdigit(s[i]); ++ i)
98 expn = expn * 10 + (s[i] - ' 0 ' );
99 expn = expn - flag;
100 power = pow( 10 , expn);
101 return sign * val * power;
102 }
103
104 power = pow( 10 , flag);
105 return sign * val / power;
106
107 }
108
109
110
111 /* ************************************************************************
112 参考代码:atof
113 ************************************************************************ */
114 /* double atof(char s[])
115 {
116
117 int i;
118 int sign;
119 //int flag;
120 int expn;
121 double val;
122 double power;
123
124 sign = 1;
125 //flag = 0;
126 power = 1.0;
127 expn = 0;
128 for(i = 0; isspace(s[i]); ++i)
129 ;
130 if(s[i] == '-')
131 sign = -1;
132 if(s[i] == '+' || s[i] == '-')
133 ++i;
134 for(val = 0.0; isdigit(s[i]); ++i)
135 val = val * 10.0 + (s[i] - '0');
136 if(s[i] == '.')
137 ++i;
138 for(; isdigit(s[i]); ++i)
139 {
140 val = val * 10.0 + (s[i] - '0');
141 power = power * 10.0;
142 //++flag;
143 }
144 val = sign * val / power;
145
146 if(s[i] == 'e' || s[i] == 'E')
147 {
148 sign = (s[++i] == '-') ? -1 : 1;
149 if(s[i] == '+' || s[i] == '-')
150 ++i;
151 for(expn = 0; isdigit(s[i]); ++i)
152 expn = expn * 10.0 + (s[i] - '0');
153 if(sign == 1)
154 while(expn-- > 0)
155 val = val * 10.0;
156 else
157 while(expn-- > 0)
158 val = val / 10.0;
159 }
160
161 return val;
162 } */

   分析:

     1,  if(s[i] == 'e' || s[i] == 'E')中,如果写成s[i++] == 'e' || s[i++] == 'E',if(s[i] == '-')

          则当输入的字符串带有E时,不能正确得到结果,这是因为在一个语句中使用两次自增操作,引起歧义

     2,  当处理含有e或E情况时,参考的atof函数代码比自定义的atof函数的代码要简洁,直观

     3,  在参考的atof函数中,用val去除10而不是用val乘以0.1的原因:0.1无法用二进制数精确地表示出来,大多数机器上

          0.1的二进制表示法都要比0.1稍微小一点,用10.0乘以0.1并不能精确地得到1.0,虽然两种做法都有误差,但是

          连续的“除以10”比连续的“乘以0.1”更精确

转载于:https://www.cnblogs.com/roma823/archive/2011/06/01/2101261.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值