练习 4-2
对 atof 函数进行扩充,使它可以处理形如
123.45e-6
的科学表示法,其中,浮点数后面可能会紧跟一个 e 或 E 以及一个指数(可能有正负号)。
原atof函数 :
double atof(char s[])
{
double val, power;
int 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;
}
/*--------------------------------
扩充代码插入位置
--------------------------------*/
return sign * val / power;
}
扩充代码 :
sign2 : 用来记录指数的正负,若指数是负数则为 1,否则为 0
double atof(char s[])
{
double power, val;
int sign, i, sign2, j, n;
for (i = 0; isspace(s[i]); i++)
;
sign = (s[i] == '-') ? -1 : 1;
if (s[i] == '-' || s[i] == '+')
i++;
for (val = 0.0; isdigit(s[i]); i++)
val = val * 10 + (s[i] - '0');
if (s[i] == '.')
i++;
for (power = 1.0; isdigit(s[i]); i++)
{
val = val * 10 + (s[i] - '0');
power *= 10;
}
//--------------------------------------------------
if (s[i] == 'e' || s[i] == 'E')
{
i++;
sign2 = (s[i] == '-') ? 1 : 0;
if (s[i] == '-' || s[i] == '+')
i++;
for (n = 0; isdigit(s[i]); i++)
n = n * 10 + (s[i] - '0');
for (j = 0; j < n; j++)
power = (sign2) ? (power * 10) : (power / 10);
}
//--------------------------------------------------
return val * sign / power;
}
若数字后面有E则进入扩展代码
第一步是读取可能存在的符号位并记录下来,若没有符号位则默认正数
第二步读取指数,然后将指数保存到 n
第三步改变 power 的值,根据 sign2 来决定是增加 power ,还是减少 power
科学计数法 aEb
表示 a 乘以 10 的 b 次方
而 power 本身就是一个 10 的幂,而且最后 val 会除以 power,
所以我这里直接对 power 进行处理,用来解决科学计数法的问题
完整代码 :
这里的 printf 函数中 使用了 “%g”
g格式:自动选f格式或e格式中较短的一种输出,且不输出无意义的零。
因为浮点型运算的误差问题,如果直接用 “%f” 会输出很恶心的东西
printf 函数参考于 “77695的自留地”
关于printf()函数和浮点数
/*练习 4-2 对 atof 函数进行扩充,使它可以处理形如
123.45e-6
的科学表示法,其中,浮点数后面可能会紧跟一个 e 或 E 以及一个指数(可能有正负号)。
*/
#include <stdio.h>
double atof(char s[]);
int isspace(int x);
int isdigit(int x);
main()
{
char num[] = " 123.456e-6";
double atof(char num[]), d;
d = atof(num);
printf("%g\n", d);
}
double atof(char s[])
{
double power, val;
int sign, i, sign2, j, n;
for (i = 0; isspace(s[i]); i++)
;
sign = (s[i] == '-') ? -1 : 1;
if (s[i] == '-' || s[i] == '+')
i++;
for (val = 0.0; isdigit(s[i]); i++)
val = val * 10 + (s[i] - '0');
if (s[i] == '.')
i++;
for (power = 1.0; isdigit(s[i]); i++)
{
val = val * 10 + (s[i] - '0');
power *= 10;
}
//--------------------------------------------------
if (s[i] == 'e' || s[i] == 'E')
{
i++;
sign2 = (s[i] == '-') ? 1 : 0;
if (s[i] == '-' || s[i] == '+')
i++;
for (n = 0; isdigit(s[i]); i++)
n = n * 10 + (s[i] - '0');
for (j = 0; j < n; j++)
power = (sign2) ? (power * 10) : (power / 10);
}
//--------------------------------------------------
return val * sign / power;
}
int isspace(int x)
{
return (x == ' ' || x == '\t' || x == '\n') ? 1 : 0;
}
int isdigit(int x)
{
return (x >= '0' && x <= '9') ? 1 : 0;
}