《C程序设计语言》练习 4-2

本文介绍如何扩展atof函数以支持科学计数法输入,如123.45e-6。通过增加对指数部分的解析,使函数能够正确计算带有指数的浮点数值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

练习 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值