Files
skyview.astronomiemuseum.de/public/js/number_to_german_words.js
T
2026-04-06 14:51:55 +02:00

124 lines
4.1 KiB
JavaScript

(function (global) {
const ONES = ['', 'eins', 'zwei', 'drei', 'vier', 'fuenf', 'sechs', 'sieben', 'acht', 'neun'];
const ONES_COMPOUND = ['', 'ein', 'zwei', 'drei', 'vier', 'fuenf', 'sechs', 'sieben', 'acht', 'neun'];
const TEENS = ['zehn', 'elf', 'zwoelf', 'dreizehn', 'vierzehn', 'fuenfzehn', 'sechzehn', 'siebzehn', 'achtzehn', 'neunzehn'];
const TENS = ['', '', 'zwanzig', 'dreissig', 'vierzig', 'fuenfzig', 'sechzig', 'siebzig', 'achtzig', 'neunzig'];
const SCALES = [
{ singular: '', plural: '', join: true },
{ singular: 'Tausend', plural: 'Tausend', join: true },
{ singular: 'Million', plural: 'Millionen', join: false },
{ singular: 'Milliarde', plural: 'Milliarden', join: false },
{ singular: 'Billion', plural: 'Billionen', join: false },
{ singular: 'Billiarde', plural: 'Billiarden', join: false },
{ singular: 'Trillion', plural: 'Trillionen', join: false },
{ singular: 'Trilliarde', plural: 'Trilliarden', join: false },
{ singular: 'Quadrillion', plural: 'Quadrillionen', join: false }
];
const GROUP_NUMBER_FORMATTER = new Intl.NumberFormat('de-DE');
function chunkToWords(value) {
if (value === 0) {
return '';
}
if (value === 1) {
return 'eins';
}
let text = '';
const hundreds = Math.floor(value / 100);
const remainder = value % 100;
if (hundreds > 0) {
text += (hundreds === 1 ? 'ein' : ONES_COMPOUND[hundreds]) + 'hundert';
}
if (remainder > 0) {
if (remainder < 10) {
text += ONES[remainder];
} else if (remainder < 20) {
text += TEENS[remainder - 10];
} else {
const ones = remainder % 10;
const tens = Math.floor(remainder / 10);
if (ones > 0) {
text += ONES_COMPOUND[ones] + 'und';
}
text += TENS[tens];
}
}
return text;
}
function integerToWords(value) {
if (!Number.isFinite(value)) {
return '';
}
if (value === 0) {
return 'null';
}
let number = Math.floor(Math.abs(value));
const groups = [];
while (number > 0) {
groups.push(number % 1000);
number = Math.floor(number / 1000);
}
const parts = [];
for (let i = groups.length - 1; i >= 0; i -= 1) {
const groupValue = groups[i];
if (groupValue === 0) {
continue;
}
const scale = SCALES[i] || { singular: '', plural: '', join: false };
if (i >= 2) {
const scaleLabel = groupValue === 1 ? scale.singular : scale.plural;
const prefix = groupValue === 1 ? 'eine' : GROUP_NUMBER_FORMATTER.format(groupValue);
parts.push(prefix + ' ' + scaleLabel);
} else if (i === 1) {
parts.push(GROUP_NUMBER_FORMATTER.format(groupValue) + ' ' + scale.singular);
} else {
parts.push(GROUP_NUMBER_FORMATTER.format(groupValue));
}
}
const result = parts.join('\n');
return value < 0 ? 'minus ' + result : result;
}
function numberToGermanText(value) {
if (!Number.isFinite(value)) {
return '';
}
const integerPart = Math.trunc(value);
const fractionalPart = Math.abs(value - integerPart);
const integerText = integerToWords(integerPart);
if (fractionalPart < 1e-10) {
return integerText;
}
const decimalDigits = fractionalPart
.toFixed(10)
.replace(/^0\./, '')
.replace(/0+$/, '')
.split('')
.map(function (digit) {
return ['null', 'eins', 'zwei', 'drei', 'vier', 'fuenf', 'sechs', 'sieben', 'acht', 'neun'][Number(digit)];
})
.join(' ');
return integerText + '\nKomma ' + decimalDigits;
}
global.numberToGermanText = numberToGermanText;
})(window);