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

- #include
- #include
- #include
-
- //自己实现字符串转浮点数,可用于某些自带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;
- }
-