Module:ConvertNumeric: Difference between revisions

m
Sync from sandbox
m (1 revision imported: Wikipedia article on Nicotine modules needed)
m (Sync from sandbox)
Line 189: Line 189:
}
}


local eng_lt20 = {
local engord_tens_end = {
['zeroth']      =  0,
['twentieth'] = 20,
['first']      =  1,
['thirtieth'] = 30,
['second']      =  2,
['fortieth'] = 40,
['third']      =  3,
['fiftieth'] = 50,
['fourth']      =  4,
['sixtieth'] = 60,
['fifth']      =  5,
['seventieth'] = 70,
['sixth']      =  6,
['eightieth'] = 80,
['seventh']    =  7,
['ninetieth'] = 90,
['eighth']      =  8,
['ninth']      =  9,
['tenth']      = 10,
['eleventh']    = 11,
['twelfth']    = 12,
['thirteenth']  = 13,
['fourteenth']  = 14,
['fifteenth']  = 15,
['sixteenth']  = 16,
['seventeenth'] = 17,
['eighteenth']  = 18,
['nineteenth']  = 19,
}
local eng_tens_end = {
['twentieth'] = 20,
['thirtieth'] = 30,
['fortieth']   = 40,
['fiftieth']   = 50,
['sixtieth']   = 60,
['seventieth'] = 70,
['eightieth'] = 80,
['ninetieth'] = 90,
}
}
local eng_tens_cont = {
local eng_tens_cont = {
['twenty'] = 20,
['twenty'] = 20,
['thirty'] = 30,
['thirty'] = 30,
['forty']   = 40,
['forty'] = 40,
['fifty']   = 50,
['fifty'] = 50,
['sixty']   = 60,
['sixty'] = 60,
['seventy'] = 70,
['seventy'] = 70,
['eighty'] = 80,
['eighty'] = 80,
['ninety'] = 90,
['ninety'] = 90,
}
}


-- Converts a given valid roman numeral (and some invalid roman numerals) to a number. Returns -1, errorstring on error
-- Converts a given valid roman numeral (and some invalid roman numerals) to a number. Returns { -1, errorstring } on error.
local function roman_to_numeral(roman)
local function roman_to_numeral(roman)
if type(roman) ~= "string" then return -1, "roman numeral not a string" end
if type(roman) ~= "string" then return -1, "roman numeral not a string" end
Line 259: Line 238:
end
end


-- Converts a given integer between 0 and 100 to English text (e.g. 47 -> forty-seven)
-- Converts a given integer between 0 and 100 to English text (e.g. 47 -> forty-seven).
local function numeral_to_english_less_100(num, ordinal, plural, zero)
local function numeral_to_english_less_100(num, ordinal, plural, zero)
local terminal_ones, terminal_tens
local terminal_ones, terminal_tens
Line 290: Line 269:
end
end


-- Converts a given integer (in string form) between 0 and 1000 to English text (e.g. 47 -> forty-seven)
-- Converts a given integer (in string form) between 0 and 1000 to English text (e.g. 47 -> forty-seven).
local function numeral_to_english_less_1000(num, use_and, ordinal, plural, zero)
local function numeral_to_english_less_1000(num, use_and, ordinal, plural, zero)
num = tonumber(num)
num = tonumber(num)
Line 302: Line 281:
end
end


-- Converts an English-text ordinal between 'zeroth' and 'ninety-ninth' to a number [0–99], else -1
-- Converts an ordinal in English text from 'zeroth' to 'ninety-ninth' inclusive to a number [0–99], else -1.
local function english_to_ordinal(english)
local function english_to_ordinal(english)
local eng = string.lower(english or '')
local eng = string.lower(english or '')
 
local eng_lt20 = eng_lt20
local engord_lt20 = {} -- ones_position_ord{} keys & values swapped
local eng_tens_end = eng_tens_end
for k, v in pairs( ones_position_ord ) do
local eng_tens_cont = eng_tens_cont
engord_lt20[v] = k
end
 
if engord_lt20[eng] then
return engord_lt20[eng] -- e.g. first -> 1
elseif engord_tens_end[eng] then
return engord_tens_end[eng] -- e.g. ninetieth -> 90
else
local tens, ones = string.match(eng, '^([a-z]+)[%s%-]+([a-z]+)$')
if tens and ones then
local tens_cont = eng_tens_cont[tens]
local ones_end  = engord_lt20[ones]
if tens_cont and ones_end then
return tens_cont + ones_end -- e.g. ninety-ninth -> 99
end
end
end
return -1 -- Failed
end
 
-- Converts a number in English text from 'zero' to 'ninety-nine' inclusive to a number [0–99], else -1.
local function english_to_numeral(english)
local eng = string.lower(english or '')
 
local eng_lt20 = { ['single'] = 1 } -- ones_position{} keys & values swapped
for k, v in pairs( ones_position ) do
eng_lt20[v] = k
end
 
if eng_lt20[eng] then
if eng_lt20[eng] then
return eng_lt20[eng] --e.g. first -> 1
return eng_lt20[eng] -- e.g. one -> 1
elseif eng_tens_end[eng] then
elseif eng_tens_cont[eng] then
return eng_tens_end[eng] --e.g. ninetieth -> 90
return eng_tens_cont[eng] -- e.g. ninety -> 90
else
else
local tens, ones = string.match(eng, '^([a-z]+)%-([a-z]+)$')
local tens, ones = string.match(eng, '^([a-z]+)[%s%-]+([a-z]+)$')
if tens and ones then
if tens and ones then
local tens_cont = eng_tens_cont[tens]
local tens_cont = eng_tens_cont[tens]
local ones_end  = eng_lt20[ones]
local ones_end  = eng_lt20[ones]
if tens_cont and ones_end then
if tens_cont and ones_end then
return tens_cont + ones_end --e.g. ninety-ninth -> 99
return tens_cont + ones_end -- e.g. ninety-nine -> 99
end
end
end
end
end
end
return -1 --failed
return -1 -- Failed
end
end


Line 380: Line 386:
end
end


-- Rounds a number to the nearest two-word number (round = up, down, or "on" for round to nearest)
-- Rounds a number to the nearest two-word number (round = up, down, or "on" for round to nearest).
-- Numbers with two digits before the decimal will be rounded to an integer as specified by round.
-- Numbers with two digits before the decimal will be rounded to an integer as specified by round.
-- Larger numbers will be rounded to a number with only one nonzero digit in front and all other digits zero.
-- Larger numbers will be rounded to a number with only one nonzero digit in front and all other digits zero.
Line 515: Line 521:
-- capitalize (boolean): whether to capitalize the result (e.g. 'One' instead of 'one')
-- capitalize (boolean): whether to capitalize the result (e.g. 'One' instead of 'one')
-- use_and (boolean): whether to use the word 'and' between tens/ones place and higher places
-- use_and (boolean): whether to use the word 'and' between tens/ones place and higher places
-- hyphenate (boolean): whether to hyphenate all words in the result, useful for use as an adjective
-- hyphenate (boolean): whether to hyphenate all words in the result, useful as an adjective
-- ordinal (boolean): whether to produce an ordinal (e.g. 'first' instead of 'one')
-- ordinal (boolean): whether to produce an ordinal (e.g. 'first' instead of 'one')
-- plural (boolean): whether to pluralize the resulting number
-- plural (boolean): whether to pluralize the resulting number
Line 656: Line 662:
roman_to_numeral = roman_to_numeral,
roman_to_numeral = roman_to_numeral,
spell_number = _numeral_to_english,
spell_number = _numeral_to_english,
spell_number2 = _numeral_to_english2,
spell_number2 = _numeral_to_english2,
english_to_ordinal = english_to_ordinal,
english_to_ordinal = english_to_ordinal,
english_to_numeral = english_to_numeral,
}
}


Line 666: Line 673:
function p._english_to_ordinal(frame) -- callable via {{#invoke:ConvertNumeric|_english_to_ordinal|First}}
function p._english_to_ordinal(frame) -- callable via {{#invoke:ConvertNumeric|_english_to_ordinal|First}}
return english_to_ordinal(frame.args[1])
return english_to_ordinal(frame.args[1])
end
function p._english_to_numeral(frame) -- callable via {{#invoke:ConvertNumeric|_english_to_numeral|One}}
return english_to_numeral(frame.args[1])
end
end


Line 707: Line 718:
if div >= 1 then return decToHexDigit(div)..dig[mod+1] else return dig[mod+1] end
if div >= 1 then return decToHexDigit(div)..dig[mod+1] else return dig[mod+1] end
end -- I think this is supposed to be done with a tail call but first I want something that works at all
end -- I think this is supposed to be done with a tail call but first I want something that works at all
---- finds all the decimal numbers in the input text and hexes each of them
---- finds all the decimal numbers in the input text and hexes each of them
function p.decToHex(frame)
function p.decToHex(frame)
Anonymous user