自行实现字符串转浮点数函数atof()

【重复造轮子的原因】

尽管atof是标准C中自带的函数,用于将字符串转为浮点数,但是在某些环境下有可能没法使用的(例如CUDA环境中,没有atof函数,但是math.h可以使用),因此自行实现。

【通过的测试用例】

【实现的代码】

#include <stdio.h>
#include <math.h>
#include <assert.h>

//自己实现字符串转浮点数,可用于某些自带atof()使用不了的环境(例如CUDA的核函数中)
double my_atof(const char *str);

//两个double是否相同(模糊比较)
bool isFuzzyEqual(double a, double b)
{
    double min  = fmin(fabs(a), fabs(b));
    double dif = fabs(a - b);
    return (dif * 1.0E12 <= min);
}

int main()
{
    assert(isFuzzyEqual(my_atof("123.456"),     123.456));
    assert(isFuzzyEqual(my_atof("0123.456"),    123.456));
    assert(isFuzzyEqual(my_atof("+123.456"),    123.456));
    assert(isFuzzyEqual(my_atof("123.456 abc"), 123.456));
    assert(isFuzzyEqual(my_atof(" 123.456 78"), 123.456));
    assert(isFuzzyEqual(my_atof("1.23456E2"),   123.456));
    assert(isFuzzyEqual(my_atof("1.23456e2"),   123.456));
    assert(isFuzzyEqual(my_atof("12345.6E-2"),  123.456));
    assert(isFuzzyEqual(my_atof("123456E-3"),   123.456));
    assert(isFuzzyEqual(my_atof("-123.456"),    -123.456));
    assert(isFuzzyEqual(my_atof("-1.23456E2"),  -123.456));
    assert(isFuzzyEqual(my_atof("0.678"),       0.678));
    assert(isFuzzyEqual(my_atof(".678"),        0.678));
    assert(isFuzzyEqual(my_atof("-.678"),       -0.678));
    assert(isFuzzyEqual(my_atof("2E-3"),        0.002));
    assert(isFuzzyEqual(my_atof("-2E-3"),       -0.002));
    assert(isFuzzyEqual(my_atof("-2.0E-3"),     -0.002));

    return 0;
}

double my_atof(const char *str)
{
    if (str == NULL)
    {
        assert(false);
        return 0.0;
    }

    int sign = 1;          //正负符号
    int sign_zhi = 1;      //指数正负符号
    double zheng = 0.0;     //整数部分
    double xiao = 0.0;      //小数部分
    int   zhi = 0;         //指数部分
    bool hasS     = false;  //是否有正负符号
    bool hasPoint = false;  //是否有小数点
    bool hasE     = false;  //是否有指数的符号E/e
    bool hasES    = false;  //是否有指数的正负符号
    int xiao_len  = 0;      //小数位长度

    int i = 0;
    const char *ps = str;

    //忽略前置空格和制表符
    while (ps[i] == ' ' || ps[i] == '\t') ++i;

    if (ps[i] == '-')
    {
        hasS = true;
        sign = -1;
        i++;
    }
    else if (ps[i] == '+')
    {
        hasS = true;
        sign = 1;
        i++;
    }

    while (true)
    {
        //中途遇到结束字符和空字符则后续被忽略
        if (ps[i] == '\0' || ps[i] == ' ' || ps[i] == '\t') break;



        if ((ps[i] >= '0' && ps[i] <= '9') || ps[i] == '-' || ps[i] == '+')
        {
            if (hasE)
            {
                if (ps[i] == '-' || ps[i] == '+')
                {
                    if (hasES)
                    {
                        assert(false); //错误格式或不识别的格式
                        return 0.0;
                    }
                    hasES = true;
                    sign_zhi = (ps[i] == '-') ? -1 : 1;
                }
                else
                {
                    zhi = zhi * 10 + (ps[i]-'0');
                }
            }
            else if (hasPoint)
            {
                if (ps[i] >= '0' && ps[i] <= '9')
                {
                    xiao_len++;
                    xiao += (ps[i] - '0') * pow(10.0, -xiao_len);
                }
                else
                {
                    assert(false); //错误格式或不识别的格式
                    return 0.0;
                }
            }
            else
            {
                if (ps[i] == '-' || ps[i] == '+')
                {
                    if (hasS)
                    {
                        assert(false); //错误格式或不识别的格式
                        return 0.0;
                    }

                    hasE = true;
                    sign = (ps[i] == '-') ? -1 : 1;
                }
                else
                {
                    zheng = zheng * 10 + (ps[i] -  '0');
                }
            }

            i++;
            continue;
        } //[+-0^9]
        else if (ps[i] == '.')
        {
            if (hasPoint)
            {
                assert(false); //错误格式或不识别的格式
                return 0.0;
            }
            hasPoint = true;
            i++;
            continue;
        }
        else if (ps[i] == 'E' || ps[i] == 'e')
        {
            if (hasE)
            {
                assert(false); //错误格式或不识别的格式
                return 0.0;
            }
            hasE = true;
            ++i;
            continue;
        }
    } // end of while

    zhi *= sign_zhi;
    double value = sign * (zheng + xiao) * pow(10, zhi);

    //TEST
    printf("TEST my_atof: %s --> %.14f\n", str, value);
    return value;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

piaopiaolanghua

感谢鼓励,再接再厉!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值