diff options
author | Ludovic Courtès <ludo@gnu.org> | 2017-02-13 21:30:51 +0100 |
---|---|---|
committer | Ludovic Courtès <ludo@gnu.org> | 2017-02-13 21:34:57 +0100 |
commit | 4b2b867c21fcf1cd751c4809edc8dc0f691daf32 (patch) | |
tree | 3051c3b6fe52938bbe80d3e978100669dab73215 | |
parent | 4aead68cdb86ca60cc372f0cd558cadda90ddec5 (diff) | |
download | guile-4b2b867c21fcf1cd751c4809edc8dc0f691daf32.tar.gz |
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.
-rw-r--r-- | doc/ref/api-i18n.texi | 10 | ||||
-rw-r--r-- | module/ice-9/i18n.scm | 40 | ||||
-rw-r--r-- | test-suite/tests/format.test | 6 | ||||
-rw-r--r-- | 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 fa3fe99d0..0a27285b1 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. -@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2009, 2010 -@c Free Software Foundation, Inc. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2006, 2007, +@c 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 2363ba350..969c0589b 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 9acbbcc22..5f433679f 100644 --- a/test-suite/tests/format.test +++ b/test-suite/tests/format.test @@ -124,13 +124,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 db7fa65e2..0475c3be5 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" |