Add Hexadecimal parsing for strtof
solve:
almost the Hexadecimal string string->float
such as:
code:float num;
const char *s= "0x123p32lala";
char *p;
num=strtof(s,&p);
printf("num is %f\n",num);
printf("str is %s\n",p);
output:num is 1249835483136.000000
str is lala
but if the input number is much big;
like:
code:const char *s2= "0x999999p100";
num=strtof(s2,&p);
printf("num is %f\n",num);
printf("str is %s\n",p);
corrent : num is 12760587998944832242938906880669384704.000000
real: num is 12760587998944800000000000000000000000.000000
it didn't have enough precision
This commit is contained in:
parent
4281acdb83
commit
fa59db8cea
2 changed files with 124 additions and 14 deletions
|
|
@ -44,6 +44,8 @@
|
|||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef CONFIG_HAVE_DOUBLE
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -80,6 +82,36 @@ static inline int is_real(double x)
|
|||
return (x < infinite) && (x >= -infinite);
|
||||
}
|
||||
|
||||
static bool chtod(char c, double base, FAR double *number)
|
||||
{
|
||||
/* This function is to determine if c is keyword
|
||||
* Then set number + base
|
||||
*/
|
||||
|
||||
double tmp = base;
|
||||
|
||||
if (isdigit(c))
|
||||
{
|
||||
tmp = c - '0';
|
||||
}
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
{
|
||||
tmp = c - 'a' + 10;
|
||||
}
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
{
|
||||
tmp = c - 'A' + 10;
|
||||
}
|
||||
|
||||
if (tmp >= base)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
*number = *number * base + tmp;
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
|
@ -140,16 +172,24 @@ double strtod(FAR const char *str, FAR char **endptr)
|
|||
break;
|
||||
}
|
||||
|
||||
p10 = 10.;
|
||||
number = 0.;
|
||||
exponent = 0;
|
||||
num_digits = 0;
|
||||
num_decimals = 0;
|
||||
|
||||
/* Process optional 0x prefix */
|
||||
|
||||
if (*p == '0' && tolower(*(p + 1)) == 'x')
|
||||
{
|
||||
p += 2;
|
||||
p10 = 16.;
|
||||
}
|
||||
|
||||
/* Process string of digits */
|
||||
|
||||
while (isdigit(*p))
|
||||
while (chtod(*p, p10, &number))
|
||||
{
|
||||
number = number * 10. + (*p - '0');
|
||||
p++;
|
||||
num_digits++;
|
||||
}
|
||||
|
|
@ -160,9 +200,8 @@ double strtod(FAR const char *str, FAR char **endptr)
|
|||
{
|
||||
p++;
|
||||
|
||||
while (isdigit(*p))
|
||||
while (chtod(*p, p10, &number))
|
||||
{
|
||||
number = number * 10. + (*p - '0');
|
||||
p++;
|
||||
num_digits++;
|
||||
num_decimals++;
|
||||
|
|
@ -188,8 +227,17 @@ double strtod(FAR const char *str, FAR char **endptr)
|
|||
|
||||
/* Process an exponent string */
|
||||
|
||||
if (*p == 'e' || *p == 'E')
|
||||
if ((p10 == 10. && (*p == 'e' || *p == 'E'))
|
||||
|| (p10 == 16. && (*p == 'p' || *p == 'P')))
|
||||
{
|
||||
/* if the Hexadecimal system */
|
||||
|
||||
if (p10 == 16.)
|
||||
{
|
||||
exponent *= 4;
|
||||
p10 = 2.0;
|
||||
}
|
||||
|
||||
/* Handle optional sign */
|
||||
|
||||
negative = 0;
|
||||
|
|
@ -240,13 +288,20 @@ double strtod(FAR const char *str, FAR char **endptr)
|
|||
exponent > __DBL_MAX_EXP__)
|
||||
{
|
||||
set_errno(ERANGE);
|
||||
number = infinite;
|
||||
if (exponent < __DBL_MIN_EXP__)
|
||||
{
|
||||
number = divzero;
|
||||
}
|
||||
else
|
||||
{
|
||||
number = infinite;
|
||||
}
|
||||
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Scale the result */
|
||||
|
||||
p10 = 10.;
|
||||
n = exponent;
|
||||
if (n < 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@
|
|||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor definitions
|
||||
****************************************************************************/
|
||||
|
|
@ -82,6 +84,36 @@ static inline int is_real(float x)
|
|||
return (x < infinite) && (x >= -infinite);
|
||||
}
|
||||
|
||||
static bool chtof(char c, float base, FAR float *number)
|
||||
{
|
||||
/* This function is to determine if c is keyword
|
||||
* Then set number + base
|
||||
*/
|
||||
|
||||
float tmp = base;
|
||||
|
||||
if (isdigit(c))
|
||||
{
|
||||
tmp = c - '0';
|
||||
}
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
{
|
||||
tmp = c - 'a' + 10;
|
||||
}
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
{
|
||||
tmp = c - 'A' + 10;
|
||||
}
|
||||
|
||||
if (tmp >= base)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
*number = *number * base + tmp;
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
|
@ -142,16 +174,24 @@ float strtof(FAR const char *str, FAR char **endptr)
|
|||
break;
|
||||
}
|
||||
|
||||
p10 = 10.0f;
|
||||
number = 0.0F;
|
||||
exponent = 0;
|
||||
num_digits = 0;
|
||||
num_decimals = 0;
|
||||
|
||||
/* Process optional 0x prefix */
|
||||
|
||||
if (*p == '0' && tolower(*(p + 1)) == 'x')
|
||||
{
|
||||
p += 2;
|
||||
p10 = 16.0f;
|
||||
}
|
||||
|
||||
/* Process string of digits */
|
||||
|
||||
while (isdigit(*p))
|
||||
while (chtof(*p, p10, &number))
|
||||
{
|
||||
number = number * 10.0F + (float)(*p - '0');
|
||||
p++;
|
||||
num_digits++;
|
||||
}
|
||||
|
|
@ -162,9 +202,8 @@ float strtof(FAR const char *str, FAR char **endptr)
|
|||
{
|
||||
p++;
|
||||
|
||||
while (isdigit(*p))
|
||||
while (chtof(*p, p10, &number))
|
||||
{
|
||||
number = number * 10.0F + (float)(*p - '0');
|
||||
p++;
|
||||
num_digits++;
|
||||
num_decimals++;
|
||||
|
|
@ -190,8 +229,17 @@ float strtof(FAR const char *str, FAR char **endptr)
|
|||
|
||||
/* Process an exponent string */
|
||||
|
||||
if (*p == 'e' || *p == 'E')
|
||||
if ((p10 == 10.0f && (*p == 'e' || *p == 'E'))
|
||||
|| (p10 == 16.0f && (*p == 'p' || *p == 'P')))
|
||||
{
|
||||
/* if the Hexadecimal system */
|
||||
|
||||
if (p10 == 16.0f)
|
||||
{
|
||||
exponent *= 4;
|
||||
p10 = 2.0f;
|
||||
}
|
||||
|
||||
/* Handle optional sign */
|
||||
|
||||
negative = 0;
|
||||
|
|
@ -242,13 +290,20 @@ float strtof(FAR const char *str, FAR char **endptr)
|
|||
exponent > __FLT_MAX_EXP__)
|
||||
{
|
||||
set_errno(ERANGE);
|
||||
number = infinite;
|
||||
if (exponent < __FLT_MIN_EXP__)
|
||||
{
|
||||
number = divzero;
|
||||
}
|
||||
else
|
||||
{
|
||||
number = infinite;
|
||||
}
|
||||
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Scale the result */
|
||||
|
||||
p10 = 10.0F;
|
||||
n = exponent;
|
||||
if (n < 0)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue