DEV Community

Multigrid
Multigrid

Posted on • Originally published at multigrid.ai

Formatting Large Numbers for a Chinese-Reading Audience

English names a new unit every three digits: thousand, million, billion. Chinese names one every four: 万 at ten thousand, 亿 at a hundred million. Every large number in generated Chinese text has to cross that boundary, and a model that translates the words without regrouping the digits produces something a reader has to convert in their head.

The myriad system

The units are powers of ten thousand rather than powers of a thousand:

个    1            one
十    10           ten
百    100          hundred
千    1 000        thousand
万    10 000       myriad          (10^4)
亿    100 000 000  hundred million (10^8)
兆    10^12        (see the caution below)
Enter fullscreen mode Exit fullscreen mode

Between 万 and 亿 there is nothing new: 十万 is ten myriad, 百万 is a hundred myriad, 千万 is a thousand myriad, and then the next named unit arrives at 亿. That is the entire mechanism, and it means the natural place to put a separator in Chinese is every four digits, not every three.

One number, two groupings

Take 123456789. Grouped the Western way and grouped the Chinese way, it splits in different places:

digits         123456789

Western        123,456,789
                 |   |   +-- 789
                 |   +------ 456 thousand
                 +---------- 123 million

Chinese        1,2345,6789
               |    |    +-- 6789
               |    +------- 2345 wan  (2345 x 10^4 = 23 450 000)
               +------------ 1    yi   (1    x 10^8 = 100 000 000)

spoken         一亿二千三百四十五万六千七百八十九
compact        1.23亿
Enter fullscreen mode Exit fullscreen mode

The two boundaries never coincide except at the start. This is why a Chinese reader shown 123,456,789 does not read it in one pass: the commas are marking positions that carry no name in their number system, so the digits have to be recounted from the right in fours before the value is legible. It is the same cognitive step an English reader performs when handed a number grouped in fours.

There is no word for million

This is the fact that produces the most awkward generated sentences. A million is 百万 — literally “hundred myriad”. A billion (10^9) is 十亿, “ten hundred-million”. Neither has a single word, and neither maps to a unit the writer can just substitute.

1 000        一千        (thousand -> qian)
10 000       一万        (no English word)
100 000      十万        (no Chinese word for hundred thousand)
1 000 000    一百万      (million -> hundred wan)
10 000 000   一千万
100 000 000  一亿        (no English word)
1 000 000 000 十亿       (billion -> ten yi)
Enter fullscreen mode Exit fullscreen mode

Look at the middle rows. There is a value with no English word (10 000) and a value with no Chinese word (100 000) within one order of magnitude of each other, which is why word-for-word translation in either direction reliably produces something clumsy. “Ten thousand” in English is a compound of a smaller unit; 十万 in Chinese is a compound of a larger one; and a model translating a marketing line like “over 500,000 users” should produce 50万, not 五百千.

The corresponding failure in the other direction is the one to watch in analytics and finance copy: 十亿 is a billion, and a model that reads 亿 as “billion” rather than “hundred million” is out by a factor of ten in a revenue figure.

What CLDR actually does

Here is the part that surprises people who go looking for four-digit grouping in locale data and cannot find it: the standard decimal pattern for Chinese locales in the Unicode CLDR uses ordinary three-digit grouping, the same as English. Digits written as digits are grouped by three; the myriad system lives in the spoken form and in the compact form.

new Intl.NumberFormat("zh-CN").format(123456789);
// "123,456,789"  -- three-digit grouping, as CLDR specifies

new Intl.NumberFormat("zh-CN", { notation: "compact" }).format(123456789);
// compact short form, built on the 万 / 亿 units from CLDR

new Intl.NumberFormat("zh-CN", { notation: "compact" }).format(12000);
// compact short form, built on 万
Enter fullscreen mode Exit fullscreen mode

The compact decimal patterns are where CLDR carries 万 and 亿, and they are specified in UTS #35, Part 3. So the practical rule for interface text is: use the platform formatter for raw figures and it will do the conventional thing, and reach for compact notation when you want the number to read the way a Chinese headline writes it. Do not hand-roll four-digit grouping into plain numerals — that is not the convention, and 1,2345,6789 in body text looks broken rather than localised.

Simplified, traditional, Japanese, Korean

The system is shared across the region; the characters are not.

  • Simplified Chinese writes 万 and 亿. Traditional Chinese — Taiwan, Hong Kong, Macau — writes 萬 and 億. Mixing them within one document is the same class of error as mixing British and American spelling, and it is a common artefact when a model converts script but not vocabulary.
  • Japanese uses 万 and 億 with the same values, and 兆 for 10^12, which is why Japanese economic reporting is full of 兆円.
  • Korean uses 만, 억 and 조 for the same three magnitudes, so Korean copy about a large budget reads in 억 and 조 just as Japanese does.
  • 兆 is the character to be careful with in Chinese. In modern mainland usage it is generally 10^12, but it has historically denoted 10^6 in some contexts and still does in a few technical usages, which is enough ambiguity that finance and government copy usually writes 万亿 for a trillion instead. If your generated text needs 10^12 in Chinese, 万亿 is the safer form.

One more variant exists that has nothing to do with magnitude: the formal financial numerals 壹 貳 參 肆 伍 陸 柒 捌 玖 拾, used on cheques and contracts specifically because they cannot be altered by adding strokes the way 一 二 三 can. Generated financial documents that need to look authentic use these; ordinary prose never does.

Getting it right in generated text

  • Keep the number out of the prose. Emit the value as a field and format it with Intl.NumberFormat for the target locale, exactly as you would for the decimal separator. The unit choice then comes from CLDR rather than from the model’s guess.
  • If the number must be spoken, say so in the prompt. “Write the figure in the way a Chinese reader would say it, using 万 and 亿 rather than translating the English unit” reliably produces 50万 rather than 五百千. Left implicit, the model frequently carries the English grouping through.
  • Fix the variant explicitly. Say zh-Hans or zh-Hant, not “Chinese”, or you will get 万 and 億 in the same paragraph.
  • Sanity-check the order of magnitude, not the wording. The high-cost error in this area is a factor of ten or a hundred in a financial figure, and it survives proofreading by anyone who does not read the language. A numeric assertion in the pipeline — that the digits in the output match the digits in the input — catches it and a translation reviewer often does not.

The same argument, with different units, applies to South Asian audiences: see the lakh and crore grouping, which breaks the digits in yet a third place.

Related

Top comments (0)