Revert "libs/libc/stdio: Fix the %f floating point output format."

The previous implementation was probably corect.  On Cygwin with GCC I see this:

int main(int argc, char **argv)
{
  printf("Value 1.2 is: [%f]\n", 1.2);
  printf("Value 0.1 is: [%f]\n", 0.1);
  printf("Value 0.0: [%f]\n", 0.0);
  printf("Value 347.6872: [%f]\n", 347.6872);
}

Generates output

Value 1.2 is: [1.200000]
Value 0.1 is: [0.100000]
Value 0.0: [0.000000]
Value 347.6872: [347.687200]

This reverts commit eb0223bc7f.
This commit is contained in:
Gregory Nutt 2019-02-15 09:59:50 -06:00
parent eb0223bc7f
commit 38e93ede2b
3 changed files with 24 additions and 50 deletions

View File

@ -121,8 +121,9 @@ config NANO_PRINTF
depends on !LIBC_LONG_LONG
---help---
Replace printf code with version from newlib-nano. This version
provides adds support for the 'g' format. However, it does not
include 'long long' support.
provides improved floating point output support, including 'g' mode
as well as making the default 'f' format include digits past the
decimal point. However, it does not include 'long long' support.
config NANO_PRINTLEVEL
int "Nano printf support level"

View File

@ -46,7 +46,6 @@
#include <nuttx/config.h>
#include <stdbool.h>
#include <math.h>
#include <assert.h>
@ -68,17 +67,6 @@
# define MAX(a,b) (a > b ? a : b)
#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
****************************************************************************/
@ -144,7 +132,6 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
{
FAR char *digits; /* String returned by __dtoa */
FAR char *rve; /* Points to the end of the return value */
bool hasdot; /* True: precision specified */
int expt; /* Integer value of exponent */
int numlen; /* Actual number of digits returned by cvt */
int nchars; /* Number of characters to print */
@ -162,14 +149,6 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
DEBUGASSERT(up_interrupt_context() == false);
#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 */
if (isnan(value))
@ -199,8 +178,8 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
/* Perform the conversion */
digits = __dtoa(value, 3, prec, &expt, &dsgn, &rve);
numlen = rve - digits;
digits = __dtoa(value, 3, prec, &expt, &dsgn, &rve);
numlen = rve - digits;
/* Avoid precision error from missing trailing zeroes */
@ -219,7 +198,7 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
* the print precision.
*/
if (value == 0 || (expt < (hasdot ? -prec : 0)))
if (value == 0 || expt < -prec)
{
/* kludge for __dtoa irregularity */
@ -229,20 +208,13 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
* particular precision is requested.
*/
if ((prec > 0 && hasdot) || IS_ALTFORM(flags))
if (prec > 0 || IS_ALTFORM(flags))
{
obj->put(obj, '.');
/* Always print at least one digit to the right of the decimal point. */
if (hasdot)
{
prec = MAX(1, prec);
}
else
{
prec = MAX(1, numlen);
}
prec = MAX(1, prec);
}
}
@ -250,6 +222,7 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
else
{
/* Handle the case where the value is less than 1.0 (in magnitude) and
* will need a leading zero.
*/
@ -266,7 +239,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 */
if (expt < 0 || hasdot)
if (expt < 0)
{
nchars = MIN(-expt, prec);
zeroes(obj, nchars);
@ -304,8 +277,7 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
* requested.
*/
if (numlen > 0 || (prec > 0 && hasdot) ||
IS_ALTFORM(flags))
if (numlen > 0 || prec > 0 || IS_ALTFORM(flags))
{
/* Print the decimal point */
@ -315,14 +287,7 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
* point.
*/
if (hasdot)
{
prec = MAX(1, prec);
}
else
{
prec = MAX(1, numlen);
}
prec = MAX(1, prec);
}
}
@ -354,10 +319,7 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
/* Finally, print any trailing zeroes */
if (hasdot)
{
zeroes(obj, prec);
}
zeroes(obj, prec);
}
/****************************************************************************

View File

@ -118,6 +118,10 @@
# define FMT_PREV src-- /* Backup to the previous character */
#endif
/* Default precision to use with %f format if no precision is specified. */
#define FLOAT_PRECISION_DEFAULT 6
/****************************************************************************
* Private Type Declarations
****************************************************************************/
@ -1555,6 +1559,13 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const IPTR char *src,
double dblval = va_arg(ap, double);
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 */
dblsize = getdblsize(FMT_CHAR, trunc, flags, dblval);