🇩🇪

Germany Number Format

CLDR Locale:
ISO: DE / DEURegion: EuropeDigits: western

Try It — Live Preview

Number
1.234.567,89
Currency (EUR)
1.234.567,89 €
Percentage
1.234.568 %
Compact
1,2 Mio.

Format Rules

Decimal Separator
,comma
Thousands Separator
.period
Grouping Pattern
3
Negative Format
-1.234.567,89
Currency Symbol
€ (EUR)
Currency Position
After number with space → 1.234.567,89 €
Percent Position
After number with space → 13 %
Zero
0,00
Compact
1,2 Mio.

Germany formatting implementation notes

For Germany, format numbers with the explicit locale de-DE; the reference value 1234567.89 renders as 1.234.567,89.

Germany's reference format uses "," as the decimal mark and period (".") for grouping. The integer uses repeating groups of three digits. Pass "de-DE" directly to Intl.NumberFormat instead of replacing punctuation in a preformatted string.

EUR is shown with € after the amount with a separating space; the same reference value renders as 1.234.567,89 €. The percent sign appears after the amount with a separating space. Use the ISO currency code for storage and interchange because a visible symbol can be shared by unrelated currencies.

Western 0–9 digits are the page's reference digit system, and the negative pattern is -n. Treat de-DE as the reference locale for this page, but still respect the user's explicitly selected language and numbering-system preferences. Validate output with formatToParts() when spacing, signs, or bidirectional literals affect the interface.

  • Locale: de-DE
  • Decimal and grouping: 1.234.567,89
  • Currency: EUR → 1.234.567,89 €
  • Digits: Western 0–9 digits

Reviewed 19 July 2026. Sources: Unicode locale number formats · Intl.NumberFormat reference

What's different here

  • Decimal mark is a comma (,) (en-US uses a period (.)).
  • Thousands are grouped with a period (.) (en-US uses a comma (,)).
  • The currency symbol goes after the amount with a space (en-US: immediately before the amount).
  • The percent sign goes after the number with a space (en-US: immediately after the number).
  • Uses the same number pattern (decimal mark, grouping, symbol and percent placement) as Denmark, Greece, Romania, Slovenia, Croatia and Serbia in Europe, plus 1 page in other regions.
  • Nearby differences: France (fr-FR) groups with a narrow no-break space (U+202F) instead of a period (.); Italy (it-IT) places the percent sign immediately after the number; Spain (es-ES) places the percent sign immediately after the number; Belgium (fr-BE) groups with a narrow no-break space (U+202F) instead of a period (.).
  • Currency: EUR has ISO minor unit 2.
  • Postal address order: name → building → street + street number → postcode + city → country. See address formats.

German number format

German (de-DE) writes 1234567.89 as 1.234.567,89: a comma for decimals, a period between thousands. The trap for English-speaking developers is reading it back, because 1.234 in a German form means one thousand two hundred thirty-four, not one point two three four. Format with Intl.NumberFormat('de-DE'), and parse with the locale's separators.

de-DE vs de-AT vs de-CH

Same language, three formats. Values are CLDR 48.2 / Intl output for 1234567.89:

de-DE (Germany)de-AT (Austria)de-CH (Switzerland)
Decimal mark,,.
Thousands (plain number).no-break space (U+00A0)apostrophe: U+0027 (CLDR 48+); U+2019 on older runtimes
Plain number1.234.567,891 234 567,891'234'567.89
Currency1.234.567,89 €€ 1.234.567,89CHF 1'234'567.89
Percent (0.13)13 %13 %13%

Two traps: de-CH uses a period for decimals, the opposite of Germany. de-AT moves the € in front of the amount and groups currency amounts with a period, but plain numbers with a space.

Parsing user input

Number() and parseFloat() only understand the English format:

Number("1.234,56");    // → NaN
parseFloat("1.234,56"); // → 1.234

parseFloat silently returns 1.234, a thousand times too small. Read the separators from the locale instead:

function parseLocaleNumber(input, locale) {
  const parts = new Intl.NumberFormat(locale).formatToParts(12345.6);
  const group = parts.find(p => p.type === 'group').value;
  const decimal = parts.find(p => p.type === 'decimal').value;
  return Number(input.trim().split(group).join('').replace(decimal, '.'));
}
parseLocaleNumber("1.234.567,89", "de-DE"); // → 1234567.89
parseLocaleNumber("1,234", "de-DE");        // → 1.234

The second result is correct German: 1,234 means one point two three four. If your form accepts both formats, ask for the locale or reject ambiguous input.

Compact notation

new Intl.NumberFormat('de-DE', { notation: 'compact' }).format(1234);          // → "1234"
new Intl.NumberFormat('de-DE', { notation: 'compact' }).format(1234567);       // → "1,2 Mio."
new Intl.NumberFormat('de-DE', { notation: 'compact' }).format(1234567890);    // → "1,2 Mrd."
new Intl.NumberFormat('de-DE', { notation: 'compact' }).format(1200000000000); // → "1,2 Bio."
new Intl.NumberFormat('de-DE', { notation: 'compact', compactDisplay: 'long' }).format(1234); // → "1,2 Tausend"

Short compact notation has no abbreviation for thousands, so 1,234 stays 1234. Use compactDisplay: 'long' if you need a word.

Q&A

Where does the € sign go in German?

In de-DE, after the amount with a space: 1.234.567,89 €. Austria (de-AT) puts it in front: € 1.234.567,89.

What do Mio., Mrd. and Bio. mean?

Millionen (10⁶), Milliarden (10⁹) and Billionen (10¹²). A German Milliarde is an English billion, and a German Billion is an English trillion, so 1,2 Bio. is 1.2 trillion. Let Intl pick the abbreviation rather than translating "B".

Is Austrian or Swiss German formatted the same as German?

No. de-CH uses a period for decimals and an apostrophe for thousands. de-AT groups plain numbers with a no-break space and puts € before the amount.

How do I read "1.234" from a German form?

As one thousand two hundred thirty-four. Parse with the locale's separators, as shown above, not with parseFloat.

Code Examples

// Basic number
new Intl.NumberFormat('de-DE').format(1234567.89)
// → "1.234.567,89"

// Currency
new Intl.NumberFormat('de-DE', {
  style: 'currency',
  currency: 'EUR'
}).format(1234567.89)
// → "1.234.567,89 €"

// Percentage
new Intl.NumberFormat('de-DE', {
  style: 'percent',
  minimumFractionDigits: 1
}).format(0.125)

// Compact notation
new Intl.NumberFormat('de-DE', {
  notation: 'compact'
}).format(1234567)

Negative Number Formats

Standard-1.234.567,89
new Intl.NumberFormat('de-DE').format(-1234567.89)
Accounting style-1.234.567,89 €
new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR', currencySign: 'accounting' }).format(-1234567.89)

Edge Cases & Notes

Period as thousands separator is the most common developer pitfall. Compact: Mio./Mrd./Bio.