Commatizing numbers: Difference between revisions
Content added Content deleted
Line 236:
=={{header|D}}==
<lang d>import std.stdio, std.regex, std.
auto commatize(bool smart=false)(in char[] txt, in uint start=0,
string ins=",", string[string] specials=null)
in {
assert(step > 0);
} body {
Line 245 ⟶ 246:
return txt;
auto scanSpan = txt[start .. $];
.replaceAll!(m => m.hit.retro.chunks(step).join(ins).retro)▼
// 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
~ matchNum.post
.replace!(m => m.hit.chunks(step).join(ins))(decField);
}
void main() {
// Current New Zealand dollar format overrides old Zimbabwe dollar format.
foreach (const line; "commatizing_numbers_data.txt".File.byLine)
line.commatize!true(0, 3, ",", ["Z$":".
}
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>
{{out}}
<pre>pi=3.14159 26535 89793 23846 26433 83279 50288 41971 69399 37510 58209 74944 59231
The author has two Z$100
"-in Aus$+1,411.8millions"
===US$0017,440 millions=== (in
123.
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.
James was never known as 0000000007
Arthur Eddington wrote: I believe there are 15
$-140,000±100 millions.
6/9/
=={{header|J}}==
|