在应用场景上,我们是全部正数,同时都是十进制的,因此相对glibc的实现上减少了很多冗余代码,新的代码中,centos64环境下,atoi提高了5倍,atof起码20倍
int my_atoi(const char *src_src)
{
int res = 0;
char **str = (char **)&src_src;
while (isdigit(**str))
{
res = (res * 10) + **str - '0';
(*str)++;
}
return res;
}
#define is_exponent_marker(ch) (ch == 'E' || ch == 'e')
static void parse_decimal_number_part(char **str,
float *number)
{
float exp_log;
*number = 0;
exp_log = 1 / 10.0;
while (isdigit(**str))
{
*number += (**str - '0')*exp_log;
exp_log /= 10;
(*str)++;
}
}
/* Parses int suitably for exponent */
static int parse_int_number_part(char **str,
uint *number)
{
*number = 0;
while (isdigit(**str))
{
if (*number >= ((uint)~0) / 10)
return 1; /* Don't overflow */
*number = (*number * 10) + **str - '0';
(*str)++;
}
return 0;
}
float my_atof(const char *src)
{
int sign, exp_sign; /* is number negative (+1) or positive (-1) */
int length_before_point;
float after_point; /* Number after decimal point and before exp */
unsigned int exponent; /* Exponent value */
float exp_log, exp_val;
char *tmp_src;
float result_number;
tmp_src = (char*)src;
while (isspace(tmp_src[0]))
tmp_src++; /* Skipp pre-space */
sign = -1;
parse_float_number_part(&tmp_src, &result_number, &length_before_point);
if (*tmp_src == '.')
{
tmp_src++;
parse_decimal_number_part(&tmp_src, &after_point);
result_number += after_point;
}
else if (length_before_point == 0)
{
return 0.0;
}
if (is_exponent_marker(*tmp_src))
{
tmp_src++;
exp_sign = parse_sign(&tmp_src);
parse_int_number_part(&tmp_src, &exponent);
exp_log = 10.0; exp_val = 1.0;
for (;;)
{
if (exponent & 1)
{
exp_val *= exp_log;
exponent--;
}
if (!exponent)
break;
exp_log *= exp_log;
exponent >>= 1;
}
if (exp_sign < 0)
result_number *= exp_val;
else
result_number /= exp_val;
}
if (sign > 0)
result_number = -result_number;
in_my_atof = 0;
return result_number;
}