mirror of
https://github.com/apache/nuttx.git
synced 2026-06-04 23:03:27 +08:00
libs/libc/stdio/lib_dtoa.c: Lots of risky turmoil to get this file closer to the NuttX coding style. Seems to check out, but still risky. libs/libc/stdio/lib_libdtoa.c: A fix for the %g format. The algorithm will sometimes generate number greater than the precision of type double. This adds a check if the precision has been exceeded and logic to remove the least significant garbage.
This commit is contained in:
+683
-526
File diff suppressed because it is too large
Load Diff
@@ -58,26 +58,20 @@
|
|||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define MAX_PREC 16
|
|
||||||
|
|
||||||
#ifndef MIN
|
#ifndef MIN
|
||||||
# define MIN(a,b) (a < b ? a : b)
|
# define MIN(a,b) (a < b ? a : b)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MAX
|
#ifndef MAX
|
||||||
# define MAX(a,b) (a > b ? a : b)
|
# define MAX(a,b) (a > b ? a : b)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Use (almost) the maximim precision with %g format if no precision is
|
/* Use the maximim precision with %g format if no precision is specified.
|
||||||
* specified. We do not use the full precision beause the least significant
|
* NOTE: This may result in numbers with precision that exceeds the
|
||||||
* digits are probably garbage.
|
* precision of type double.
|
||||||
*
|
|
||||||
* REVISIT: This should be smarter. 15 digits is the maximum size of the
|
|
||||||
* number. The maximum precision is really 15 minus the number of digits
|
|
||||||
* in the integer part.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define DOUBLE_PRECISON_MAX 13 /* vs 15 which is the maximum */
|
#define DOUBLE_PRECISON_MAX 15
|
||||||
|
|
||||||
/* Use a default precision of 6 for the %f format if no precision is
|
/* Use a default precision of 6 for the %f format if no precision is
|
||||||
* specified.
|
* specified.
|
||||||
@@ -107,6 +101,24 @@ static void zeroes(FAR struct lib_outstream_s *obj, int nzeroes)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: truncate_zeroes
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Adjust the string length to eliminate zeros in the fractional part of
|
||||||
|
* the string.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static inline int truncate_zeroes(FAR char *digits, int expt, int numlen)
|
||||||
|
{
|
||||||
|
for (; numlen > expt && digits[numlen - 1] == '0'; numlen--)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return numlen;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: lib_dtoa_string
|
* Name: lib_dtoa_string
|
||||||
*
|
*
|
||||||
@@ -216,6 +228,28 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
|
|||||||
digits = __dtoa(value, 3, prec, &expt, &dsgn, &rve);
|
digits = __dtoa(value, 3, prec, &expt, &dsgn, &rve);
|
||||||
numlen = rve - digits;
|
numlen = rve - digits;
|
||||||
|
|
||||||
|
/* If we are going to truncate trailing zeros, then make sure we have not
|
||||||
|
* exceeded the precision of type double.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (notrailing && numlen > DOUBLE_PRECISON_MAX)
|
||||||
|
{
|
||||||
|
/* Make sure there are fractional digits to truncate */
|
||||||
|
|
||||||
|
if (expt <= DOUBLE_PRECISON_MAX)
|
||||||
|
{
|
||||||
|
numlen = DOUBLE_PRECISON_MAX;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
numlen = expt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Shortening the string probably now exposes some trailing zeroes */
|
||||||
|
|
||||||
|
numlen = truncate_zeroes(digits, expt, numlen);
|
||||||
|
}
|
||||||
|
|
||||||
/* Avoid precision error from missing trailing zeroes */
|
/* Avoid precision error from missing trailing zeroes */
|
||||||
|
|
||||||
numlen = MAX(expt, numlen);
|
numlen = MAX(expt, numlen);
|
||||||
|
|||||||
Reference in New Issue
Block a user