Fix more floating point formatting bugs
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5013 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
495c45d4f6
commit
4346670013
@ -3129,4 +3129,6 @@
|
|||||||
point numbers (conversions are fine, but presentation was bad). This
|
point numbers (conversions are fine, but presentation was bad). This
|
||||||
is a critical bug fix if you use printf or sprintf to deal with floating
|
is a critical bug fix if you use printf or sprintf to deal with floating
|
||||||
point numbers.
|
point numbers.
|
||||||
|
* lib/stdio/lib_libdtoa.c and lib_libvsprintf.c: Correct some floating
|
||||||
|
point options.
|
||||||
|
|
||||||
|
@ -48,6 +48,8 @@
|
|||||||
* 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
|
||||||
@ -107,7 +109,20 @@ static void zeroes(FAR struct lib_outstream_s *obj, int nzeroes)
|
|||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* This is part of lib_vsprintf(). It handles the floating point formats.
|
* This is part of lib_vsprintf(). It handles the floating point formats.
|
||||||
* This version supports only the &f (with precision).
|
* This version supports only the %f (with precision). If no precision
|
||||||
|
* was provided in the format, this will use precision == 0 which is
|
||||||
|
* probably not what you want.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* obj - The output stream object
|
||||||
|
* fmt - The format character. Not used 'f' is always assumed
|
||||||
|
* prec - The number of digits to the right of the decimal point. If no
|
||||||
|
* precision is provided in the format, this will be zero. And,
|
||||||
|
* unfortunately in this case, it will be treated literally as
|
||||||
|
* a precision of zero.
|
||||||
|
* flags - Only ALTFORM and SHOWPLUS flags are supported. ALTFORM only
|
||||||
|
* applies if prec == 0 which is not supported anyway.
|
||||||
|
* value - The floating point value to convert.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
@ -146,10 +161,10 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
|
|||||||
{
|
{
|
||||||
obj->put(obj, '-');
|
obj->put(obj, '-');
|
||||||
}
|
}
|
||||||
|
else if (IS_SHOWPLUS(flags))
|
||||||
/* Always print at least one digit to the right of the decimal point. */
|
{
|
||||||
|
obj->put(obj, '+');
|
||||||
prec = MAX(1, prec);
|
}
|
||||||
|
|
||||||
/* Special case exact zero or the case where the number is smaller than
|
/* Special case exact zero or the case where the number is smaller than
|
||||||
* the print precision.
|
* the print precision.
|
||||||
@ -160,53 +175,101 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
|
|||||||
/* kludge for __dtoa irregularity */
|
/* kludge for __dtoa irregularity */
|
||||||
|
|
||||||
obj->put(obj, '0');
|
obj->put(obj, '0');
|
||||||
obj->put(obj, '.');
|
|
||||||
}
|
|
||||||
else if (expt <= 0)
|
|
||||||
{
|
|
||||||
obj->put(obj, '0');
|
|
||||||
obj->put(obj, '.');
|
|
||||||
|
|
||||||
/* Print leading zeros */
|
/* A decimal point is printed only in the alternate form or if a
|
||||||
|
* particular precision is requested.
|
||||||
|
*/
|
||||||
|
|
||||||
if (expt < 0)
|
if (prec > 0 || IS_ALTFORM(flags))
|
||||||
{
|
{
|
||||||
nchars = MIN(-expt, prec);
|
obj->put(obj, '.');
|
||||||
zeroes(obj, nchars);
|
|
||||||
prec -= nchars;
|
/* Always print at least one digit to the right of the decimal point. */
|
||||||
|
|
||||||
|
prec = MAX(1, prec);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print the significant digits */
|
|
||||||
|
|
||||||
nchars = MIN(numlen, prec);
|
|
||||||
for (i = nchars; i > 0; i--)
|
|
||||||
{
|
|
||||||
obj->put(obj, *digits);
|
|
||||||
digits++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decremnt to get the number of trailing zeroes to print */
|
|
||||||
|
|
||||||
prec -= nchars;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* A non-zero value will be printed */
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Print the integer part */
|
|
||||||
|
|
||||||
for (i = expt; i > 0; i--)
|
/* Handle the case where the value is less than 1.0 (in magnitude) and
|
||||||
|
* will need a leading zero.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (expt <= 0)
|
||||||
{
|
{
|
||||||
obj->put(obj, *digits);
|
/* Print a single zero to the left of the decimal point */
|
||||||
digits++;
|
|
||||||
|
obj->put(obj, '0');
|
||||||
|
|
||||||
|
/* Print the decimal point */
|
||||||
|
|
||||||
|
obj->put(obj, '.');
|
||||||
|
|
||||||
|
/* Print any leading zeros to the right of the decimal point */
|
||||||
|
|
||||||
|
if (expt < 0)
|
||||||
|
{
|
||||||
|
nchars = MIN(-expt, prec);
|
||||||
|
zeroes(obj, nchars);
|
||||||
|
prec -= nchars;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print the decimal place */
|
/* Handle the general case where the value is greater than 1.0 (in
|
||||||
|
* magnitude).
|
||||||
|
*/
|
||||||
|
|
||||||
obj->put(obj, '.');
|
else
|
||||||
|
{
|
||||||
|
/* Print the integer part to the left of the decimal point */
|
||||||
|
|
||||||
/* Print the decimal */
|
for (i = expt; i > 0; i--)
|
||||||
|
{
|
||||||
|
obj->put(obj, *digits);
|
||||||
|
digits++;
|
||||||
|
}
|
||||||
|
|
||||||
numlen -= expt;
|
/* Get the length of the fractional part */
|
||||||
nchars = MIN(numlen, prec);
|
|
||||||
|
numlen -= expt;
|
||||||
|
|
||||||
|
/* If there is no fractional part, then a decimal point is printed
|
||||||
|
* only in the alternate form or if a particular precision is
|
||||||
|
* requested.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (numlen > 0 || prec > 0 || IS_ALTFORM(flags))
|
||||||
|
{
|
||||||
|
/* Print the decimal point */
|
||||||
|
|
||||||
|
obj->put(obj, '.');
|
||||||
|
|
||||||
|
/* Always print at least one digit to the right of the decimal
|
||||||
|
* point.
|
||||||
|
*/
|
||||||
|
|
||||||
|
prec = MAX(1, prec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If a precision was specified, then limit the number digits to the
|
||||||
|
* right of the decimal point.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (prec > 0)
|
||||||
|
{
|
||||||
|
nchars = MIN(numlen, prec);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nchars = numlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print the fractional part to the right of the decimal point */
|
||||||
|
|
||||||
for (i = nchars; i > 0; i--)
|
for (i = nchars; i > 0; i--)
|
||||||
{
|
{
|
||||||
|
@ -1587,7 +1587,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const char *src, va_list a
|
|||||||
|
|
||||||
/* Perform left field justification actions */
|
/* Perform left field justification actions */
|
||||||
|
|
||||||
prejustify(obj, fmt, flags, width, dblsize);
|
prejustify(obj, fmt, 0, width, dblsize);
|
||||||
|
|
||||||
/* Output the number */
|
/* Output the number */
|
||||||
|
|
||||||
@ -1595,7 +1595,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const char *src, va_list a
|
|||||||
|
|
||||||
/* Perform right field justification actions */
|
/* Perform right field justification actions */
|
||||||
|
|
||||||
postjustify(obj, fmt, flags, width, dblsize);
|
postjustify(obj, fmt, 0, width, dblsize);
|
||||||
#else
|
#else
|
||||||
/* Output the number with a fixed precision */
|
/* Output the number with a fixed precision */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user