[m-rev.] for review: format ints with thousand separators

Julien Fischer juliensf at cs.mu.OZ.AU
Thu Feb 3 17:02:44 AEDT 2005


On Thu, 3 Feb 2005, Ian MacLarty wrote:

> 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
s/Add predicate/Add a predicate/

> 	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.
> +
Do we really need the predicate version?

>  	% 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".
> +	%
This comment should mention that it throws an exception if the Base is not
between 2 and 36.

> +:- 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.
> +
Likewise, are we really going to need a predicate verson of this?


>  	% 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)
> +		)
> +	).
>

That looks ok otherwise.

Julien.
--------------------------------------------------------------------------
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