astronomical_conversions verbessert
This commit is contained in:
@@ -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(' ');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user