guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] 13/14: i18n: 'number->locale-string' guesses the minimum


From: Andy Wingo
Subject: [Guile-commits] 13/14: i18n: 'number->locale-string' guesses the minimum number of decimals.
Date: Wed, 1 Mar 2017 15:21:05 -0500 (EST)

wingo pushed a commit to branch master
in repository guile.

commit de5cf50aba1b9fd43c1fbd653c5cd9b7b973d52b
Author: Ludovic Courtès <address@hidden>
Date:   Mon Feb 13 21:30:51 2017 +0100

    i18n: 'number->locale-string' guesses the minimum number of decimals.
    
    This feature was removed by 4aead68cdb86ca60cc372f0cd558cadda90ddec5.
    
    * module/ice-9/i18n.scm (number-decimal-string): Rewrite the case where
    DIGIT-COUNT is not an integer.
    (number->locale-string): Always pass FRACTION-DIGITS to
    'number-decimal-string'.
    * test-suite/tests/format.test ("~h localized number")["1234.5"]
    ["padding", "padchar"]: Remove decimal specifier.
    * test-suite/tests/i18n.test ("number->locale-string")
    ["fraction",
    * test-suite/tests/i18n.test ("format ~h")["12 345,678"]: Remove decimal
    specifier.  Remove one decimal.
    * doc/ref/api-i18n.texi (Number Input and Output): Update
    'number->locale-string' doc to mention the number of decimals.
---
 doc/ref/api-i18n.texi        | 10 ++++++----
 module/ice-9/i18n.scm        | 40 +++++++++++++++++++++++++++-------------
 test-suite/tests/format.test |  6 +++---
 test-suite/tests/i18n.test   | 16 ++++++++--------
 4 files changed, 44 insertions(+), 28 deletions(-)

diff --git a/doc/ref/api-i18n.texi b/doc/ref/api-i18n.texi
index fa3fe99..0a27285 100644
--- a/doc/ref/api-i18n.texi
+++ b/doc/ref/api-i18n.texi
@@ -1,7 +1,7 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Guile Reference Manual.
address@hidden Copyright (C)  1996, 1997, 2000, 2001, 2002, 2003, 2004, 2006, 
2007, 2009, 2010
address@hidden   Free Software Foundation, Inc.
address@hidden Copyright (C)  1996, 1997, 2000, 2001, 2002, 2003, 2004, 2006, 
2007,
address@hidden   2009, 2010, 2017 Free Software Foundation, Inc.
 @c See the file guile.texi for copying conditions.
 
 @node Internationalization
@@ -263,8 +263,10 @@ Reference Manual}).
 @deffn {Scheme Procedure} number->locale-string number [fraction-digits 
[locale]]
 Convert @var{number} (an inexact) into a string according to the
 cultural conventions of either @var{locale} (a locale object) or the
-current locale.  Optionally, @var{fraction-digits} may be bound to an
-integer specifying the number of fractional digits to be displayed.
+current locale.  By default, print as many fractional digits as
+necessary, up to an upper bound.  Optionally, @var{fraction-digits} may
+be bound to an integer specifying the number of fractional digits to be
+displayed.
 @end deffn
 
 @deffn {Scheme Procedure} monetary-amount->locale-string amount intl? [locale]
diff --git a/module/ice-9/i18n.scm b/module/ice-9/i18n.scm
index 2363ba3..969c058 100644
--- a/module/ice-9/i18n.scm
+++ b/module/ice-9/i18n.scm
@@ -262,19 +262,35 @@
                         digits))))))
 
 (define (number-decimal-string number digit-count)
-  "Return a string representing the decimal part of NUMBER, with exactly
-DIGIT-COUNT digits"
-  (if (integer? number)
-      (make-string digit-count #\0)
-
-      ;; XXX: This is brute-force and could be improved by following one
-      ;; of the "Printing Floating-Point Numbers Quickly and Accurately"
-      ;; papers.
+  "Return a string representing the decimal part of NUMBER.  When
+DIGIT-COUNT is an integer, return exactly DIGIT-COUNT digits; when
+DIGIT-COUNT is #t, return as many decimals as necessary, up to an
+arbitrary limit."
+  (define max-decimals
+    5)
+
+  ;; XXX: This is brute-force and could be improved by following one of
+  ;; the "Printing Floating-Point Numbers Quickly and Accurately"
+  ;; papers.
+  (if (integer? digit-count)
       (let ((number (* (expt 10 digit-count)
                        (- number (floor number)))))
         (string-pad (integer->string (round (inexact->exact number)))
                     digit-count
-                    #\0))))
+                    #\0))
+      (let loop ((decimals 0))
+        (let ((number' (* number (expt 10 decimals))))
+          (if (or (= number' (floor number'))
+                  (>= decimals max-decimals))
+              (let* ((fraction (- number'
+                                  (* (floor number)
+                                     (expt 10 decimals))))
+                     (str      (integer->string
+                                (round (inexact->exact fraction)))))
+                (if (zero? fraction)
+                    ""
+                    str))
+              (loop (+ decimals 1)))))))
 
 (define (%number-integer-part int grouping separator)
   ;; Process INT (a string denoting a number's integer part) and return a new
@@ -399,6 +415,7 @@ locale is used."
                                            (locale %global-locale))
   "Convert @var{number} (an inexact) into a string according to the cultural
 conventions of either @var{locale} (a locale object) or the current locale.
+By default, print as many fractional digits as necessary, up to an upper bound.
 Optionally, @var{fraction-digits} may be bound to an integer specifying the
 number of fractional digits to be displayed."
 
@@ -421,10 +438,7 @@ number of fractional digits to be displayed."
                                         (floor (abs number)))))
            (dec       (decimal-part
                        (number-decimal-string (abs number)
-                                              (if (integer?
-                                                   fraction-digits)
-                                                  fraction-digits
-                                                  0))))
+                                              fraction-digits)))
            (grouping  (locale-digit-grouping locale))
            (separator (locale-thousands-separator locale)))
 
diff --git a/test-suite/tests/format.test b/test-suite/tests/format.test
index 302feac..b9aa7a8 100644
--- a/test-suite/tests/format.test
+++ b/test-suite/tests/format.test
@@ -133,13 +133,13 @@
 (with-test-prefix "~h localized number"
 
   (pass-if "1234.5"
-    (string=? (format #f "~,1h" 1234.5) "1234.5"))
+    (string=? (format #f "~h" 1234.5) "1234.5"))
 
   (pass-if "padding"
-    (string=? (format #f "~6h" 123.2) "   123"))
+    (string=? (format #f "~6h" 123.2) " 123.2"))
 
   (pass-if "padchar"
-    (string=? (format #f "~8,1,'*h" 123.2) "***123.2"))
+    (string=? (format #f "~8,,'*h" 123.2) "***123.2"))
 
   (pass-if "decimals"
     (string=? (format #f "~,2h" 123.4567)
diff --git a/test-suite/tests/i18n.test b/test-suite/tests/i18n.test
index db7fa65..0475c3b 100644
--- a/test-suite/tests/i18n.test
+++ b/test-suite/tests/i18n.test
@@ -506,7 +506,7 @@
 
     (pass-if-equal "fraction"
         "1234.567"
-      (number->locale-string 1234.567 3))
+      (number->locale-string 1234.567))
 
     (pass-if-equal "fraction, 1 digit"
         "1234.6"
@@ -545,7 +545,7 @@
       (under-french-locale-or-unresolved
        (lambda ()
          (let ((fr (make-locale LC_ALL %french-locale-name)))
-           (number->locale-string 1234.567 3 fr)))))
+           (number->locale-string 1234.567 #t fr)))))
 
     (pass-if-equal "fraction, 1 digit"
         "1 234,6"
@@ -562,23 +562,23 @@
 
   (with-test-prefix "French"
 
-    (pass-if-equal "12345.6789"
-        "12 345,6789"
+    (pass-if-equal "12345.678"
+        "12 345,678"
       (under-french-locale-or-unresolved
        (lambda ()
          (if (null? (locale-digit-grouping %french-locale))
              (throw 'unresolved)
-             (format #f "~,4:h" 12345.6789 %french-locale))))))
+             (format #f "~:h" 12345.678 %french-locale))))))
 
   (with-test-prefix "English"
 
-    (pass-if-equal "12345.6789"
-        "12,345.6789"
+    (pass-if-equal "12345.678"
+        "12,345.678"
       (under-american-english-locale-or-unresolved
        (lambda ()
          (if (null? (locale-digit-grouping %american-english-locale))
              (throw 'unresolved)
-             (format #f "~,4:h" 12345.6789
+             (format #f "~:h" 12345.678
                      %american-english-locale)))))))
 
 (with-test-prefix "monetary-amount->locale-string"



reply via email to

[Prev in Thread] Current Thread [Next in Thread]