astronomical_conversions verbessert

This commit is contained in:
2026-04-11 12:13:54 +02:00
parent 8083c731f7
commit 0504c7d03b
2 changed files with 434 additions and 123 deletions
+66 -39
View File
@@ -3,19 +3,18 @@
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 DIGIT_WORDS = ['null', 'eins', 'zwei', 'drei', 'vier', 'fuenf', 'sechs', 'sieben', 'acht', 'neun'];
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 }
{ singular: '', plural: '' },
{ singular: 'Tausend', plural: 'Tausend' },
{ singular: 'Million', plural: 'Millionen' },
{ singular: 'Milliarde', plural: 'Milliarden' },
{ singular: 'Billion', plural: 'Billionen' },
{ singular: 'Billiarde', plural: 'Billiarden' },
{ singular: 'Trillion', plural: 'Trillionen' },
{ singular: 'Trilliarde', plural: 'Trilliarden' },
{ singular: 'Quadrillion', plural: 'Quadrillionen' }
];
const GROUP_NUMBER_FORMATTER = new Intl.NumberFormat('de-DE');
function chunkToWords(value) {
if (value === 0) {
@@ -52,67 +51,95 @@
return text;
}
function integerToWords(value) {
if (!Number.isFinite(value)) {
function normalizeGermanNumberString(value) {
if (typeof value === 'number') {
if (!Number.isFinite(value)) {
return '';
}
return String(value).replace('.', ',');
}
if (typeof value !== 'string') {
return '';
}
if (value === 0) {
return value.trim().replace(/\s+/g, '');
}
function splitNormalizedNumber(value) {
const normalized = normalizeGermanNumberString(value);
if (normalized === '') {
return null;
}
const sign = normalized.startsWith('-') ? '-' : '';
const unsigned = sign ? normalized.slice(1) : normalized;
const cleaned = unsigned.replace(/\./g, '');
const parts = cleaned.split(',');
if (parts.length > 2) {
return null;
}
const integerPart = (parts[0] || '0').replace(/^0+(?=\d)/, '') || '0';
const fractionalPart = parts[1] || '';
if (!/^\d+$/.test(integerPart) || (fractionalPart !== '' && !/^\d+$/.test(fractionalPart))) {
return null;
}
return { sign, integerPart, fractionalPart };
}
function integerStringToWords(integerString, sign) {
if (integerString === '0') {
return 'null';
}
let number = Math.floor(Math.abs(value));
const groups = [];
while (number > 0) {
groups.push(number % 1000);
number = Math.floor(number / 1000);
for (let index = integerString.length; index > 0; index -= 3) {
groups.push(integerString.slice(Math.max(0, index - 3), index));
}
const parts = [];
for (let i = groups.length - 1; i >= 0; i -= 1) {
const groupValue = groups[i];
const groupValue = Number(groups[i]);
if (groupValue === 0) {
continue;
}
const scale = SCALES[i] || { singular: '', plural: '', join: false };
const scale = SCALES[i] || { singular: '', plural: '' };
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);
const prefix = groupValue === 1 ? 'eine' : String(groupValue);
const label = groupValue === 1 ? scale.singular : scale.plural;
parts.push(prefix + ' ' + label);
} else if (i === 1) {
parts.push(GROUP_NUMBER_FORMATTER.format(groupValue) + ' ' + scale.singular);
parts.push(groupValue === 1 ? 'ein ' + scale.singular : String(groupValue) + ' ' + scale.singular);
} else {
parts.push(GROUP_NUMBER_FORMATTER.format(groupValue));
parts.push(String(groupValue));
}
}
const result = parts.join('\n');
return value < 0 ? 'minus ' + result : result;
return sign === '-' ? 'minus ' + result : result;
}
function numberToGermanText(value) {
if (!Number.isFinite(value)) {
const parsed = splitNormalizedNumber(value);
if (!parsed) {
return '';
}
const integerPart = Math.trunc(value);
const fractionalPart = Math.abs(value - integerPart);
const integerText = integerToWords(integerPart);
if (fractionalPart < 1e-10) {
const integerText = integerStringToWords(parsed.integerPart, parsed.sign);
if (!parsed.fractionalPart || /^0+$/.test(parsed.fractionalPart)) {
return integerText;
}
const decimalDigits = fractionalPart
.toFixed(10)
.replace(/^0\./, '')
.replace(/0+$/, '')
const decimalDigits = parsed.fractionalPart
.split('')
.map(function (digit) {
return ['null', 'eins', 'zwei', 'drei', 'vier', 'fuenf', 'sechs', 'sieben', 'acht', 'neun'][Number(digit)];
return DIGIT_WORDS[Number(digit)];
})
.join(' ');