mirror of
https://github.com/apache/nuttx.git
synced 2026-06-04 14:53:47 +08:00
libs/libc/stdio: Fix the %f floating point output format.
This commit is contained in:
@@ -121,9 +121,8 @@ config NANO_PRINTF
|
|||||||
depends on !LIBC_LONG_LONG
|
depends on !LIBC_LONG_LONG
|
||||||
---help---
|
---help---
|
||||||
Replace printf code with version from newlib-nano. This version
|
Replace printf code with version from newlib-nano. This version
|
||||||
provides improved floating point output support, including 'g' mode
|
provides adds support for the 'g' format. However, it does not
|
||||||
as well as making the default 'f' format include digits past the
|
include 'long long' support.
|
||||||
decimal point. However, it does not include 'long long' support.
|
|
||||||
|
|
||||||
config NANO_PRINTLEVEL
|
config NANO_PRINTLEVEL
|
||||||
int "Nano printf support level"
|
int "Nano printf support level"
|
||||||
|
|||||||
@@ -46,6 +46,7 @@
|
|||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
@@ -67,6 +68,17 @@
|
|||||||
# define MAX(a,b) (a > b ? a : b)
|
# define MAX(a,b) (a > b ? a : b)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Use (almost) the maximim precision with %f format if no precision is
|
||||||
|
* specified. We do not use the full precision beause the least significant
|
||||||
|
* digits are probably garbage.
|
||||||
|
*
|
||||||
|
* 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 */
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -132,6 +144,7 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
|
|||||||
{
|
{
|
||||||
FAR char *digits; /* String returned by __dtoa */
|
FAR char *digits; /* String returned by __dtoa */
|
||||||
FAR char *rve; /* Points to the end of the return value */
|
FAR char *rve; /* Points to the end of the return value */
|
||||||
|
bool hasdot; /* True: precision specified */
|
||||||
int expt; /* Integer value of exponent */
|
int expt; /* Integer value of exponent */
|
||||||
int numlen; /* Actual number of digits returned by cvt */
|
int numlen; /* Actual number of digits returned by cvt */
|
||||||
int nchars; /* Number of characters to print */
|
int nchars; /* Number of characters to print */
|
||||||
@@ -149,6 +162,14 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
|
|||||||
DEBUGASSERT(up_interrupt_context() == false);
|
DEBUGASSERT(up_interrupt_context() == false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Set to default precision if none specified */
|
||||||
|
|
||||||
|
hasdot = IS_HASDOT(flags);
|
||||||
|
if (!hasdot && prec == 0)
|
||||||
|
{
|
||||||
|
prec = DOUBLE_PRECISON_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
/* Special handling for NaN and Infinity */
|
/* Special handling for NaN and Infinity */
|
||||||
|
|
||||||
if (isnan(value))
|
if (isnan(value))
|
||||||
@@ -178,8 +199,8 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
|
|||||||
|
|
||||||
/* Perform the conversion */
|
/* Perform the conversion */
|
||||||
|
|
||||||
digits = __dtoa(value, 3, prec, &expt, &dsgn, &rve);
|
digits = __dtoa(value, 3, prec, &expt, &dsgn, &rve);
|
||||||
numlen = rve - digits;
|
numlen = rve - digits;
|
||||||
|
|
||||||
/* Avoid precision error from missing trailing zeroes */
|
/* Avoid precision error from missing trailing zeroes */
|
||||||
|
|
||||||
@@ -198,7 +219,7 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
|
|||||||
* the print precision.
|
* the print precision.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (value == 0 || expt < -prec)
|
if (value == 0 || (expt < (hasdot ? -prec : 0)))
|
||||||
{
|
{
|
||||||
/* kludge for __dtoa irregularity */
|
/* kludge for __dtoa irregularity */
|
||||||
|
|
||||||
@@ -208,13 +229,20 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
|
|||||||
* particular precision is requested.
|
* particular precision is requested.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (prec > 0 || IS_ALTFORM(flags))
|
if ((prec > 0 && hasdot) || IS_ALTFORM(flags))
|
||||||
{
|
{
|
||||||
obj->put(obj, '.');
|
obj->put(obj, '.');
|
||||||
|
|
||||||
/* Always print at least one digit to the right of the decimal point. */
|
/* Always print at least one digit to the right of the decimal point. */
|
||||||
|
|
||||||
prec = MAX(1, prec);
|
if (hasdot)
|
||||||
|
{
|
||||||
|
prec = MAX(1, prec);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
prec = MAX(1, numlen);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,7 +250,6 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
|
|||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Handle the case where the value is less than 1.0 (in magnitude) and
|
/* Handle the case where the value is less than 1.0 (in magnitude) and
|
||||||
* will need a leading zero.
|
* will need a leading zero.
|
||||||
*/
|
*/
|
||||||
@@ -239,7 +266,7 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
|
|||||||
|
|
||||||
/* Print any leading zeros to the right of the decimal point */
|
/* Print any leading zeros to the right of the decimal point */
|
||||||
|
|
||||||
if (expt < 0)
|
if (expt < 0 || hasdot)
|
||||||
{
|
{
|
||||||
nchars = MIN(-expt, prec);
|
nchars = MIN(-expt, prec);
|
||||||
zeroes(obj, nchars);
|
zeroes(obj, nchars);
|
||||||
@@ -277,7 +304,8 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
|
|||||||
* requested.
|
* requested.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (numlen > 0 || prec > 0 || IS_ALTFORM(flags))
|
if (numlen > 0 || (prec > 0 && hasdot) ||
|
||||||
|
IS_ALTFORM(flags))
|
||||||
{
|
{
|
||||||
/* Print the decimal point */
|
/* Print the decimal point */
|
||||||
|
|
||||||
@@ -287,7 +315,14 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
|
|||||||
* point.
|
* point.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
prec = MAX(1, prec);
|
if (hasdot)
|
||||||
|
{
|
||||||
|
prec = MAX(1, prec);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
prec = MAX(1, numlen);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,7 +354,10 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
|
|||||||
|
|
||||||
/* Finally, print any trailing zeroes */
|
/* Finally, print any trailing zeroes */
|
||||||
|
|
||||||
zeroes(obj, prec);
|
if (hasdot)
|
||||||
|
{
|
||||||
|
zeroes(obj, prec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
@@ -118,10 +118,6 @@
|
|||||||
# define FMT_PREV src-- /* Backup to the previous character */
|
# define FMT_PREV src-- /* Backup to the previous character */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Default precision to use with %f format if no precision is specified. */
|
|
||||||
|
|
||||||
#define FLOAT_PRECISION_DEFAULT 6
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Type Declarations
|
* Private Type Declarations
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -1559,13 +1555,6 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const IPTR char *src,
|
|||||||
double dblval = va_arg(ap, double);
|
double dblval = va_arg(ap, double);
|
||||||
int dblsize;
|
int dblsize;
|
||||||
|
|
||||||
/* Set to default precision if none specified */
|
|
||||||
|
|
||||||
if (!IS_HASDOT(flags) && trunc == 0)
|
|
||||||
{
|
|
||||||
trunc = FLOAT_PRECISION_DEFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the width of the output */
|
/* Get the width of the output */
|
||||||
|
|
||||||
dblsize = getdblsize(FMT_CHAR, trunc, flags, dblval);
|
dblsize = getdblsize(FMT_CHAR, trunc, flags, dblval);
|
||||||
|
|||||||
Reference in New Issue
Block a user