Module:ConvertNumeric

Documentation for this module may be created at Module:ConvertNumeric/doc

-- Module for converting between different representations of numbers
-- Adapted to handle variants (e.g., default, 'c', etc.)

require('strict')

-- Default variant and additional variant 'c'
local variants = {
    default = {
        ones_position = {
            [0] = 'cero',
            [1] = 'un',
            [2] = 'dos',
            [3] = 'tres',
            [4] = 'cuatro',
            [5] = 'cinco',
            [6] = 'seis',
            [7] = 'siete',
            [8] = 'ocho',
            [9] = 'nueve',
            [10] = 'diez',
            [11] = 'once',
            [12] = 'doce',
            [13] = 'trece',
            [14] = 'catorce',
            [15] = 'quince',
            [16] = 'dieciséis',
            [17] = 'diecisiete',
            [18] = 'dieciocho',
            [19] = 'diecinueve'
        },
        tens_position = {
            [2] = 'veinte',
            [3] = 'treinta',
            [4] = 'cuarenta',
            [5] = 'cincuenta',
            [6] = 'sesenta',
            [7] = 'setenta',
            [8] = 'ochenta',
            [9] = 'noventa'
        },
        groups = {
            [1] = 'mil',
            [2] = 'millón',
            [3] = 'billón',
            [4] = 'trillón'
            -- Add more as needed
        }
    },
    c = {
        ones_position = {
            [0] = 'sero',
            [1] = 'uno',
            [2] = 'do',
            [3] = 'tre',
            [4] = 'quatro',
            [5] = 'cinco',
            [6] = 'sei',
            [7] = 'sete',
            [8] = 'ocho',
            [9] = 'nueve',
            [10] = 'die',
            [11] = 'onceuno',
            [12] = 'oncesdo',
            [13] = 'onctre',
            [14] = 'oncequatro',
            [15] = 'oncecinco',
            [16] = 'oncesseis',
            [17] = 'oncsiete',
            [18] = 'oncocho',
            [19] = 'oncnueve'
        },
        tens_position = {
            [2] = 'binti',
            [3] = 'trinta',
            [4] = 'quarenta',
            [5] = 'cincuenta',
            [6] = 'sesenta',
            [7] = 'setenta',
            [8] = 'ochenta',
            [9] = 'nobenta'
        },
        groups = {
            [1] = 'mil',
            [2] = 'miom',
            [3] = 'biyon'
            -- Add more as needed
        }
    }
}

local function get_variant_table(variant)
    return variants[variant] or variants.default
end

local function numeral_to_english_less_100(num, variant, ordinal, plural, zero)
    local tables = get_variant_table(variant)
    local terminal_ones = ordinal and ones_position_ord or (plural and ones_position_plural or tables.ones_position)
    local terminal_tens = ordinal and tens_position_ord or (plural and tens_position_plural or tables.tens_position)

    if num == 0 and zero then
        return zero
    elseif num < 20 then
        return terminal_ones[num]
    elseif num % 10 == 0 then
        return terminal_tens[num / 10]
    else
        return terminal_tens[math.floor(num / 10)] .. '-' .. terminal_ones[num % 10]
    end
end

local function numeral_to_english_less_1000(num, variant, use_and, ordinal, plural, zero)
    num = tonumber(num)
    local tables = get_variant_table(variant)
    if num < 100 then
        return numeral_to_english_less_100(num, variant, ordinal, plural, zero)
    elseif num % 100 == 0 then
        return tables.ones_position[math.floor(num / 100)] .. ' hundred' .. (ordinal and 'th' or (plural and 's' or ''))
    else
        return tables.ones_position[math.floor(num / 100)] .. ' hundred ' .. (use_and and 'and ' or '') .. numeral_to_english_less_100(num % 100, variant, ordinal, plural, zero)
    end
end

local function _numeral_to_english(num, variant, numerator, denominator, capitalize, use_and, hyphenate, ordinal, plural, links, negative_word, round, zero, use_one)
    local tables = get_variant_table(variant)
    num = scientific_notation_to_decimal(num)
    if round and round ~= '' then
        num = round_for_english(num, round)
    end

    local MINUS = '−'
    if num:sub(1, #MINUS) == MINUS then
        num = '-' .. num:sub(#MINUS + 1)
    elseif num:sub(1, 1) == '+' then
        num = num:sub(2)
    end
    local negative = num:find("^%-")
    local decimal_places, subs = num:gsub("^%-?%d*%.(%d+)$", "%1")
    if subs == 0 then decimal_places = nil end
    num, subs = num:gsub("^%-?(%d*)%.?%d*$", "%1")
    if num == '' and decimal_places then num = '0' end
    if subs == 0 or num == '' then error("Invalid decimal numeral") end

    local s = ''
    while #num > 3 do
        if s ~= '' then s = s .. ' ' end
        local group_num = math.floor((#num - 1) / 3)
        local group = tables.groups[group_num]
        local group_digits = #num - group_num * 3
        s = s .. numeral_to_english_less_1000(num:sub(1, group_digits), variant, false, false, false, nil) .. ' ' .. group
        num = num:sub(group_digits + 1)
    end
    s = s .. numeral_to_english_less_1000(num, variant, false, false, false, nil)
    if negative then s = 'minus ' .. s end
    if capitalize then s = s:gsub("^%l", string.upper) end
    if hyphenate then s = s:gsub("%s", "-") end
    return s
end

-- Example usage:
print(_numeral_to_english("1234", "default", nil, nil, false, true, false, false, false, nil, nil, nil, nil, nil))
print(_numeral_to_english("1234", "c", nil, nil, false, true, false, false, false, nil, nil, nil, nil, nil))