[m-rev.] for review: format ints with thousand separators
Ian MacLarty
maclarty at cs.mu.OZ.AU
Thu Feb 3 16:52:52 AEDT 2005
For review by anyone.
Estimated hours taken: 2
Branches: main
Add predicates and functions to the string module to format integers with
thousand separators.
library/string.m
Add predicate and function to convert an int to a string with
commas as thousand separators. Add a predicate and function to
convert an int to any base with any string between any number of
digits.
tests/general/string_test.exp
tests/general/string_test.m
Test the new functionality.
Index: library/string.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/string.m,v
retrieving revision 1.226
diff -u -r1.226 string.m
--- library/string.m 2 Feb 2005 04:28:49 -0000 1.226
+++ library/string.m 3 Feb 2005 05:50:13 -0000
@@ -119,6 +119,13 @@
:- pred string__int_to_string(int, string).
:- mode string__int_to_string(in, uo) is det.
+ % Convert an integer to a string with commas as thousand seperators.
+ %
+:- func string__int_to_string_thousands(int) = string.
+:- mode string__int_to_string_thousands(in) = uo is det.
+:- pred string__int_to_string_thousands(int, string).
+:- mode string__int_to_string_thousands(in, uo) is det.
+
% string__int_to_base_string(Int, Base, String):
% Convert an integer to a string in a given Base (between 2 and 36).
%
@@ -127,6 +134,17 @@
:- pred string__int_to_base_string(int, int, string).
:- mode string__int_to_base_string(in, in, uo) is det.
+ % string__int_to_base_string_group(Int, Base, GroupLength, Seperator,
+ % String):
+ % Convert an integer to a string in a given Base (between 2 and 36)
+ % and insert Seperator between every GroupLength digits. Useful
+ % for formatting numbers like "1,300,000".
+ %
+:- func string__int_to_base_string_group(int, int, int, string) = string.
+:- mode string__int_to_base_string_group(in, in, in, in) = uo is det.
+:- pred string__int_to_base_string_group(int, int, int, string, string).
+:- mode string__int_to_base_string_group(in, in, in, in, uo) is det.
+
% Convert a float to a string.
% In the current implementation the resulting float will be in the
% form that it was printed using the format string "%#.<prec>g".
@@ -941,6 +959,73 @@
string__from_char_list(CharList, Str) :-
string__to_char_list(Str, CharList).
+
+string__int_to_string_thousands(N) = Str :-
+ string__int_to_base_string_group(N, 10, 3, ",", Str).
+
+string__int_to_string_thousands(N, Str) :-
+ string__int_to_base_string_group(N, 10, 3, ",", Str).
+
+string__int_to_base_string_group(N, Base, Period, Sep) = Str :-
+ string__int_to_base_string_group(N, Base, Period, Sep, Str).
+
+string__int_to_base_string_group(N, Base, Period, Sep, Str) :-
+ (
+ Base >= 2, Base =< 36
+ ->
+ true
+ ;
+ error("string__int_to_base_string_group: invalid base")
+ ),
+ string__int_to_base_string_group_1(N, Base, Period, Sep, Str).
+
+:- pred string__int_to_base_string_group_1(int::in, int::in, int::in,
+ string::in, string::uo) is det.
+
+string__int_to_base_string_group_1(N, Base, Period, Sep, Str) :-
+ % Note that in order to handle MININT correctly,
+ % we need to do the conversion of the absolute
+ % number into digits using negative numbers
+ % (we can't use positive numbers, since -MININT overflows)
+ (
+ N < 0
+ ->
+ string__int_to_base_string_group_2(N, Base, 0, Period, Sep,
+ Str1),
+ string__append("-", Str1, Str)
+ ;
+ N1 = 0 - N,
+ string__int_to_base_string_group_2(N1, Base, 0, Period, Sep,
+ Str)
+ ).
+
+:- pred string__int_to_base_string_group_2(int::in, int::in, int::in, int::in,
+ string::in, string::uo) is det.
+
+string__int_to_base_string_group_2(NegN, Base, Curr, Period, Sep, Str) :-
+ (
+ Curr = Period, Period > 0
+ ->
+ string__int_to_base_string_group_2(NegN, Base, 0, Period, Sep,
+ Str1),
+ string__append(Str1, Sep, Str)
+ ;
+ (
+ NegN > -Base
+ ->
+ N = -NegN,
+ char__det_int_to_digit(N, DigitChar),
+ string__char_to_string(DigitChar, Str)
+ ;
+ NegN1 = NegN // Base,
+ N10 = (NegN1 * Base) - NegN,
+ char__det_int_to_digit(N10, DigitChar),
+ string__char_to_string(DigitChar, DigitString),
+ string__int_to_base_string_group_2(NegN1, Base,
+ Curr + 1, Period, Sep, Str1),
+ string__append(Str1, DigitString, Str)
+ )
+ ).
/*-----------------------------------------------------------------------*/
Index: tests/general/string_test.exp
===================================================================
RCS file: /home/mercury1/repository/tests/general/string_test.exp,v
retrieving revision 1.1
diff -u -r1.1 string_test.exp
--- tests/general/string_test.exp 4 Nov 1996 07:08:47 -0000 1.1
+++ tests/general/string_test.exp 3 Feb 2005 05:32:52 -0000
@@ -6,6 +6,10 @@
int_to_string 1234: 1234
octal 1234: 2322
hexadecimal 1234: 4D2
+Grouped 1234: 1,234
+Grouped 113: 1--1--1--0--0--0--1
+Grouped 1300000: 1,300,000
+Non Grouped 45999: 45999
string_to_int 5678: 5678
Five f's: fffff
Five f's and five dots: fffff.....
Index: tests/general/string_test.m
===================================================================
RCS file: /home/mercury1/repository/tests/general/string_test.m,v
retrieving revision 1.3
diff -u -r1.3 string_test.m
--- tests/general/string_test.m 1 Dec 2003 15:56:07 -0000 1.3
+++ tests/general/string_test.m 3 Feb 2005 05:30:40 -0000
@@ -31,6 +31,14 @@
write_message("octal 1234: ", Num8),
{ string__int_to_base_string(1234, 16, Num16) },
write_message("hexadecimal 1234: ", Num16),
+ { string__int_to_base_string_group(1234, 10, 3, ",", NumG1) },
+ write_message("Grouped 1234: ", NumG1),
+ { string__int_to_base_string_group(113, 2, 1, "--", NumG2) },
+ write_message("Grouped 113: ", NumG2),
+ { string__int_to_base_string_group(1300000, 10, 3, ",", NumG3) },
+ write_message("Grouped 1300000: ", NumG3),
+ { string__int_to_base_string_group(45999, 10, 0, ",", NumG4) },
+ write_message("Non Grouped 45999: ", NumG4),
{ string__duplicate_char('f', 5, FiveFs) },
( { string__to_int("5678", Num5678) } ->
io__write_string("string_to_int 5678: "),
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list