(format "%d" F) now truncates floating F
Problem reported by Paul Pogonyshev (Bug#31938). * src/editfns.c: Include math.h, for trunc. (styled_format): For %d, truncate floating-point numbers and convert -0 to 0, going back to how Emacs 26 did things. * doc/lispref/strings.texi (Formatting Strings): Document behavior of %o, %d, %x, %X on floating-point numbers. * src/floatfns.c (trunc) [!HAVE_TRUNC]: Rename from emacs_trunc and make it an extern function, so that editfns.c can use it. All callers changed. * test/src/editfns-tests.el (format-%d-float): New test.
This commit is contained in:
parent
27a21970f6
commit
d0e2a341dd
5 changed files with 32 additions and 12 deletions
|
@ -922,18 +922,23 @@ Functions}). Thus, strings are enclosed in @samp{"} characters, and
|
|||
@item %o
|
||||
@cindex integer to octal
|
||||
Replace the specification with the base-eight representation of an
|
||||
unsigned integer.
|
||||
unsigned integer. The object can also be a nonnegative floating-point
|
||||
number that is formatted as an integer, dropping any fraction, if the
|
||||
integer does not exceed machine limits.
|
||||
|
||||
@item %d
|
||||
Replace the specification with the base-ten representation of a signed
|
||||
integer.
|
||||
integer. The object can also be a floating-point number that is
|
||||
formatted as an integer, dropping any fraction.
|
||||
|
||||
@item %x
|
||||
@itemx %X
|
||||
@cindex integer to hexadecimal
|
||||
Replace the specification with the base-sixteen representation of an
|
||||
unsigned integer. @samp{%x} uses lower case and @samp{%X} uses upper
|
||||
case.
|
||||
case. The object can also be a nonnegative floating-point number that
|
||||
is formatted as an integer, dropping any fraction, if the integer does
|
||||
not exceed machine limits.
|
||||
|
||||
@item %c
|
||||
Replace the specification with the character which is the value given.
|
||||
|
|
|
@ -47,6 +47,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
#include <errno.h>
|
||||
#include <float.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef HAVE_TIMEZONE_T
|
||||
# include <sys/param.h>
|
||||
|
@ -4671,6 +4672,12 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
|
|||
{
|
||||
strcpy (f - pMlen - 1, "f");
|
||||
double x = XFLOAT_DATA (arg);
|
||||
|
||||
/* Truncate and then convert -0 to 0, to be more
|
||||
consistent with %x etc.; see Bug#31938. */
|
||||
x = trunc (x);
|
||||
x = x ? x : 0;
|
||||
|
||||
sprintf_bytes = sprintf (sprintf_buf, convspec, 0, x);
|
||||
char c0 = sprintf_buf[0];
|
||||
bool signedp = ! ('0' <= c0 && c0 <= '9');
|
||||
|
|
|
@ -435,11 +435,9 @@ emacs_rint (double d)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TRUNC
|
||||
#define emacs_trunc trunc
|
||||
#else
|
||||
static double
|
||||
emacs_trunc (double d)
|
||||
#ifndef HAVE_TRUNC
|
||||
double
|
||||
trunc (double d)
|
||||
{
|
||||
return (d < 0 ? ceil : floor) (d);
|
||||
}
|
||||
|
@ -482,8 +480,7 @@ Rounds ARG toward zero.
|
|||
With optional DIVISOR, truncate ARG/DIVISOR. */)
|
||||
(Lisp_Object arg, Lisp_Object divisor)
|
||||
{
|
||||
return rounding_driver (arg, divisor, emacs_trunc, truncate2,
|
||||
"truncate");
|
||||
return rounding_driver (arg, divisor, trunc, truncate2, "truncate");
|
||||
}
|
||||
|
||||
|
||||
|
@ -543,7 +540,7 @@ DEFUN ("ftruncate", Fftruncate, Sftruncate, 1, 1, 0,
|
|||
{
|
||||
CHECK_FLOAT (arg);
|
||||
double d = XFLOAT_DATA (arg);
|
||||
d = emacs_trunc (d);
|
||||
d = trunc (d);
|
||||
return make_float (d);
|
||||
}
|
||||
|
||||
|
|
|
@ -3425,8 +3425,11 @@ extern Lisp_Object string_make_unibyte (Lisp_Object);
|
|||
extern void syms_of_fns (void);
|
||||
|
||||
/* Defined in floatfns.c. */
|
||||
extern void syms_of_floatfns (void);
|
||||
#ifndef HAVE_TRUNC
|
||||
extern double trunc (double);
|
||||
#endif
|
||||
extern Lisp_Object fmod_float (Lisp_Object x, Lisp_Object y);
|
||||
extern void syms_of_floatfns (void);
|
||||
|
||||
/* Defined in fringe.c. */
|
||||
extern void syms_of_fringe (void);
|
||||
|
|
|
@ -176,6 +176,14 @@
|
|||
(should-error (format "%o" -1e-37)
|
||||
:type 'overflow-error))
|
||||
|
||||
;; Bug#31938
|
||||
(ert-deftest format-%d-float ()
|
||||
(should (string-equal (format "%d" -1.1) "-1"))
|
||||
(should (string-equal (format "%d" -0.9) "0"))
|
||||
(should (string-equal (format "%d" -0.0) "0"))
|
||||
(should (string-equal (format "%d" 0.0) "0"))
|
||||
(should (string-equal (format "%d" 0.9) "0"))
|
||||
(should (string-equal (format "%d" 1.1) "1")))
|
||||
|
||||
;;; Check format-time-string with various TZ settings.
|
||||
;;; Use only POSIX-compatible TZ values, since the tests should work
|
||||
|
|
Loading…
Add table
Reference in a new issue