Commatizing numbers: Difference between revisions

Content added Content deleted
Line 236: Line 236:


=={{header|D}}==
=={{header|D}}==
<lang d>import std.stdio, std.regex, std.string, std.range, std.conv;
<lang d>import std.stdio, std.regex, std.range, std.array, std.algorithm, std.typecons;

auto commatize(in char[] txt, in uint start=0, in uint step=3, in string ins=",")
auto commatize(bool smart=false)(in char[] txt, in uint start=0, uint step=3,
string ins=",", string[string] specials=null)
/*pure nothrow*/ @safe in {
in {
assert(step > 0);
assert(step > 0);
} body {
} body {
Line 245: Line 246:
return txt;
return txt;


return txt[0 .. start] ~ txt[start .. $]
auto preSpan = txt[0 .. start];
auto scanSpan = txt[start .. $];
.replaceAll!(m => m.hit.retro.chunks(step).join(ins).retro)

("[1-9][0-9]*".regex);
// The first number field begins with zero then no digit, or non-zero.
auto numField = regex("0(?![0-9])|[1-9][0-9]*");
auto matchNum = matchFirst(scanSpan, numField);

if (!matchNum)
return txt;

// Pass only a point and capture a decimal fractional field, if any.
auto decField = regex("(?<=^\\.)[0-9]+");

static if (smart) {
// A fractional part over 33 digits needs a word for less than a
// decillionth (to read aloud in US number names).
// Group by 5 with spaces to read like scientific notation instead.
auto matchDec = matchFirst(matchNum.post, decField);
if (matchDec && matchDec.hit.length > 33) {
step = 5;
ins = " ";
}
// A whole part over 36 digits needs a word for more than a decillion
// (to read aloud in US number names).
// Group anyway, with spaces as in the task's Wikipedia reference.
else if (matchNum.hit.length > 36) {
ins = " ";
}
}

// There may be special prefixed formats that use different separators.
// Any format with a longer prefix should override a shorter one.
Tuple!(string, string)[] pairs;
foreach (pair; specials.byPair) {
pairs ~= pair;
}
std.algorithm.sort!("a[0].length < b[0].length")(pairs);
foreach (symbol; pairs) {
if (matchNum.pre.length >= symbol[0].length &&
symbol[0] == matchNum.pre[$ - symbol[0].length .. $])
ins = symbol[1];
}

return preSpan ~ matchNum.pre ~ matchNum.hit
.replace!(m => m.hit.retro.chunks(step).join(ins).retro)(numField)
~ matchNum.post
.replace!(m => m.hit.chunks(step).join(ins))(decField);
}
}


void main() {
void main() {
// Current New Zealand dollar format overrides old Zimbabwe dollar format.
foreach (const line; "commatizing_numbers_data.txt".File.byLine)
foreach (const line; "commatizing_numbers_data.txt".File.byLine)
line.commatize.write;
line.commatize!true(0, 3, ",", ["Z$":".", "NZ$":","]).writeln;
}

unittest {
assert("0.0123456".commatize == "0.012,345,6");
assert("1. NZ$300000".commatize(1, 3, " ", ["Z$":".", "NZ$":","]) ==
"1. NZ$300,000");
assert("1000 2.3000".commatize == "1,000 2.3000");
assert("0001123.456789".commatize == "0001,123.456,789");
}</lang>
}</lang>
{{out}}
{{out}}
<pre>pi=3.14159 26535 89793 23846 26433 83279 50288 41971 69399 37510 58209 74944 59231
<pre>pi=3.14,159,265,358,979,323,846,264,338,327,950,288,419,716,939,937,510,582,097,494,459,231
The author has two Z$100,000,000,000,000 Zimbabwe notes (100 trillion).
The author has two Z$100.000.000.000.000 Zimbabwe notes (100 trillion).
"-in Aus$+1,411.8millions"
"-in Aus$+1,411.8millions"
===US$0017,440 millions=== (in 2,000 dollars)
===US$0017,440 millions=== (in 2000 dollars)
123.e8,000 is pretty big.
123.e8000 is pretty big.
The land area of the earth is 57,268,900(29% of the surface) square miles.
The land area of the earth is 57,268,900(29% of the surface) square miles.
Ain't no numbers in this here words, nohow, no way, Jose.
Ain't no numbers in this here words, nohow, no way, Jose.
James was never known as 0000000007
James was never known as 0000000007
Arthur Eddington wrote: I believe there are 15,747,724,136,275,002,577,605,653,961,181,555,468,044,717,914,527,116,709,366,231,425,076,185,631,031,296 protons in the universe.
Arthur Eddington wrote: I believe there are 15 747 724 136 275 002 577 605 653 961 181 555 468 044 717 914 527 116 709 366 231 425 076 185 631 031 296 protons in the universe.
$-140,000±100 millions.
$-140,000±100 millions.
6/9/1,946 was a good year for some.</pre>
6/9/1946 was a good year for some.</pre>


=={{header|J}}==
=={{header|J}}==