Open
Description
相比strtod,效率更高并且Locale-independant,支持最长1,000,000个字符长度的数字:
#include <ctype.h>
#include <math.h>
double evaluate_json_number(const char *integer, const char *fraction, int exp)
{
long long mant = 0;
int figures = 0;
double num;
int sign;
sign = (*integer == '-');
if (sign)
integer++;
if (*integer != '0')
{
mant = *integer - '0';
integer++;
figures++;
while (isdigit(*integer) && figures < 18)
{
mant *= 10;
mant += *integer - '0';
integer++;
figures++;
}
while (isdigit(*integer))
{
exp++;
integer++;
}
}
else
{
while (*fraction == '0')
{
exp--;
fraction++;
}
}
while (isdigit(*fraction) && figures < 18)
{
mant *= 10;
mant += *fraction - '0';
exp--;
fraction++;
figures++;
}
if (exp != 0 && figures != 0)
{
while (exp > 0 && figures < 18)
{
mant *= 10;
exp--;
figures++;
}
while (exp < 0 && mant % 10 == 0)
{
mant /= 10;
exp++;
figures--;
}
}
num = mant;
if (exp != 0 && figures != 0)
{
if (exp > 291)
num = INFINITY;
else if (exp > 0)
num *= pow(10, exp);
else if (exp > -309)
num /= pow(10, -exp);
else if (exp > -324 - figures)
{
num /= pow(10, -exp - 308);
num /= pow(10, 308);
}
else
num = 0.0;
}
return sign ? -num : num;
}
int parse_json_number(const char *cursor, const char **end, double *num)
{
const char *integer = cursor;
const char *fraction = "";
int exp = 0;
int sign;
if (*cursor == '-')
cursor++;
if (!isdigit(*cursor))
return -1;
if (*cursor == '0' && isdigit(cursor[1]))
return -1;
cursor++;
while (isdigit(*cursor))
cursor++;
if (*cursor == '.')
{
cursor++;
fraction = cursor;
if (!isdigit(*cursor))
return -1;
cursor++;
while (isdigit(*cursor))
cursor++;
}
if (*cursor == 'E' || *cursor == 'e')
{
cursor++;
sign = (*cursor == '-');
if (sign || *cursor == '+')
cursor++;
if (!isdigit(*cursor))
return -1;
exp = *cursor - '0';
cursor++;
while (isdigit(*cursor) && exp < 2000000)
{
exp *= 10;
exp += *cursor - '0';
cursor++;
}
while (isdigit(*cursor))
cursor++;
if (sign)
exp = -exp;
}
if (cursor - integer > 1000000)
return -1;
*num = evaluate_json_number(integer, fraction, exp);
*end = cursor;
return 0;
}
#include <stdio.h>
int main()
{
const char *text = "4.94e-324";
const char *end;
double num;
parse_json_number(text, &end, &num);
printf("num = %le, len = %zu\n", num, end - text);
return 0;
}
完整的json-parser实现:https://github.com/barenboim/json-parser
Metadata
Metadata
Assignees
Labels
No labels