polish-number-to-words
Version:
Spell numbers using words in Polish | Napisz liczbę słownie po polsku
77 lines (76 loc) • 2.8 kB
JavaScript
import { getDecimalPlaces } from './_utils';
import { commonFractionToWordsPL } from './commonFractionToWords';
import { integerToWordsPL } from './integerToWords';
const WORDS_0_TO_9 = [
'zero',
'jeden',
'dwa',
'trzy',
'cztery',
'pięć',
'sześć',
'siedem',
'osiem',
'dziewięć',
];
/**
* Converts a decimal fraction into Polish words.
* Can return either a full fractional phrase (e.g., "dwanaście tysięcznych") or a digit-by-digit form (e.g., "przecinek dwanaście"). Ignores the minus sign.
*
* @param num A non-integer number between 0 and 1 (e.g., 0.25, 0.125, etc.).
* @param options Optional settings to customize the output style.
* @throws Will throw if an integer is provided instead of a decimal fraction.
* @returns A string representing the decimal fraction in Polish, ignoring the minus.
*/
export function decimalFractionToWordsPL(num, options) {
const optionsWithDefaults = {
informal: false,
informalFormIndividualNumberThreshold: 4,
simplifyFraction: false,
...(options ?? {}),
};
const isNegative = num < 0;
num = Math.abs(num);
if (num % 1 === 0) {
throw new Error("Provided number isn't a fraction and cannot be spelled as a decimal fraction");
}
const decimalPlaces = getDecimalPlaces(num);
if (!optionsWithDefaults.informal) {
const fractionNumerator = fractionToInteger(num);
const fractionDenominator = 10 ** decimalPlaces;
if (!optionsWithDefaults.simplifyFraction) {
return commonFractionToWordsPL(fractionNumerator, fractionDenominator);
}
const fraction = simplifyFraction(fractionNumerator, fractionDenominator);
return commonFractionToWordsPL(fraction.numerator, fraction.denominator);
}
const numAsString = num.toString().split('.')[1];
const parts = ['przecinek'];
if (decimalPlaces < optionsWithDefaults.informalFormIndividualNumberThreshold) {
parts.push(integerToWordsPL(Number(numAsString)));
}
else {
parts.push(...numAsString
.split('')
.slice(0, decimalPlaces)
.map(v => WORDS_0_TO_9[Number(v)]));
}
return parts.filter(Boolean).join(' ');
}
function fractionToInteger(n) {
const decimalPlaces = getDecimalPlaces(n);
return Math.round(n * 10 ** decimalPlaces);
}
function simplifyFraction(numerator, denominator) {
const gcd = greatestCommonDivisor(Math.abs(numerator), Math.abs(denominator));
return {
numerator: numerator / gcd,
denominator: denominator / gcd,
};
}
function greatestCommonDivisor(a, b) {
while (b !== 0) {
[a, b] = [b, a % b];
}
return a;
}