【重复造轮子的原因】
尽管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;
}