果酸有什么作用| 血糖高的人早餐吃什么好| 诸位是什么意思| 肾构错瘤要注意什么| ana谱是查什么病的| 孩子为什么长不高| 快闪店是什么意思| 吃什么对肠道好| 划扣是什么意思| 石榴是什么生肖| 磨牙是什么原因引起的| 甲胎蛋白偏高是什么原因| 幼儿急疹为什么不能碰水| 五戒十善是什么| 梨状肌综合症吃什么药| 早上吃什么好| 什么叫边界感| 十点半是什么时辰| 血管是什么颜色的| 胃胀消化不好吃什么药| 裹小脚是什么时候开始的| 痛风什么引起的原因有哪些| 什么头十足| 广肚是什么| 后会无期什么意思| 异位性皮炎是什么意思| 勃而不坚吃什么药| 包饺子什么馅好吃| 喜上眉梢是什么意思| 绿豆和什么相克中毒| 笔触是什么意思| 吃什么有助于骨头愈合| 医生为什么穿白大褂| 身体缺钾吃什么可以补充| 跳蛋有什么用| 晚上吃什么水果减肥效果最好| 网络绿茶是什么意思| tpo是什么| 超声检查是什么| 经常手淫对身体有什么危害| 血氧低吃什么药| 麸子是什么东西| 燕子喜欢吃什么| alpha什么意思| 梦见杀鸡是什么意思| 晚上喝柠檬水有什么好处| 茉莉茶叶有什么功效和作用| 产生幻觉是什么原因| 1965属什么生肖| 等是什么生肖| 经常口臭的人是什么原因引起的| 仓鼠能吃什么东西| 羊的尾巴有什么作用| 来例假不能吃什么| 1978年是什么年| 家里为什么有隐翅虫| 92年属猴是什么命| 明天我要离开是什么歌| 吐血是什么病| 黄精什么功效| 胃黏膜病变是什么意思| 沈阳为什么叫盛京| 什么是苔藓皮肤病| 东京热是什么| 感冒咳嗽一直不好是什么原因| 鸡蛋干配什么菜炒好吃| 红底白杠是什么标志| 手指头发麻是什么原因引起的| kappa是什么牌子| 食物不耐受是什么意思| 眼前发黑是什么原因| 宫颈转化区三型是什么意思| 女性肾功能不好有什么症状| 莲蓬乳是什么| 腋毛有什么作用| 有代沟是什么意思| 如意丹的作用是什么| 眼黄瘤什么方法治疗最好| 首鼠两端是什么意思| 买房要看什么| 无花果有什么好处| 血小板减少是什么症状| 世界上最长的河流是什么| 男生剪什么发型好看| 结膜充血用什么眼药水| 事业是什么意思| 阴虚内热是什么意思| 为什么夏天吃姜好| 女人排卵期是什么时候| mds是什么意思| 什么是血铅| 秋天可以干什么| 湖北人喜欢吃什么菜| 毒龙什么意思| 爿是什么意思| 祖先是什么意思| 胃充盈欠佳是什么意思| 春肖是什么生肖| 什么是热射病| 克罗恩病有什么症状| 什么炖鸡汤好喝又营养| 乂是什么意思| 什么是三高| 不完全骨折是什么意思| cheblo空调是什么牌子| 每天一杯蜂蜜水有什么好处| 7.23是什么星座| 开胸手术吃什么补元气| 婴儿吃不饱有什么危害| 母亲节送什么花| 阴郁是什么意思| 2月25号是什么星座| 肛裂是什么感觉| 重楼别名叫什么| 喉咙痛吃什么水果| 滢字五行属什么| 宁字属于五行属什么| 慢性扁桃体炎吃什么药| 指甲凹凸不平什么原因| a型血和b型血生的孩子是什么血型| 心气不足吃什么中成药| 胚芽是什么意思| 百合有什么功效| 一什么手表| torch什么意思| 石女什么样| 什么食物补钾| 制作人是干什么的| 湿疹是什么样子| 徽音是什么意思| 咽喉炎吃什么药| 梦见别人生孩子预示什么| gaba是什么| hf是什么| 手麻了是什么原因| 小孩突然抽搐失去意识是什么原因| 流鼻血吃什么| 天线宝宝都叫什么名字| 低血钾吃什么补上来的快| 黄豆酱做什么菜好吃| 范仲淹世称什么| 阳虚吃什么药| 含服是什么意思| 射精出血是什么原因| 荨麻疹有什么症状| 什么是内分泌| 8月5日什么星座| 清江鱼是什么鱼| 牛肉炒什么| 什么是童话故事| 薄荷叶晒干后能干什么| o.o什么意思| ooc什么意思| 微针有什么功效| 冬虫夏草什么价格| 肩周炎用什么药最好| alt医学上是什么意思| 眩晕停又叫什么| kitty什么意思| 右耳朵发热代表什么预兆| 罗嘉良为什么娶苏岩| 什么是冰丝面料| 抑郁挂什么科| 水加人念什么| 大佐相当于中国的什么军衔| 空心菜不能和什么一起吃| 活死人是什么意思| 改善记忆力吃什么药好| 1966年是什么命| 亲吻是什么感觉| emma什么意思| 咳白色泡沫痰是什么病| 鲛人是什么意思| 风热感冒咳嗽吃什么药| 脑袋进水什么意思| 下面有异味是什么原因| 暴露是什么意思| 付诸行动是什么意思| 男性内分泌失调吃什么药| 勤劳的小蜜蜂什么意思| 六月二十八是什么日子| d g是什么牌子| 病是什么结构| 屁股出汗多是什么原因| 半夜是什么时辰| 旭五行属性是什么| 什么败走华容道不出所料| 1926年属什么| 兰花用什么土栽培最好| 92年的属什么| 商鞅姓什么| 什么症状| 心脏是由什么组织构成的| 什么是矫正视力| 1989年属什么的| 急火攻心是什么生肖| 气色是什么意思| 梦见办丧事是什么兆头| 前列腺炎吃什么消炎药好| 儿童弱视是什么原因引起的| 肝在人体什么位置| 经停是什么意思| 美女的胸长什么样| 后是什么意思| 大林木命忌讳什么颜色| 什么鼻子好看| 溃疡性结肠炎吃什么药| 男生做爱什么感觉| 胃不舒服恶心想吐吃什么药| 吃什么可以提高免疫力和抵抗力| 为什么会有霉菌性阴道炎| 儿童办理身份证需要什么材料| 热锅凉油是什么意思| 龋齿是什么原因造成的| 戊土是什么土| 为什么飞机起飞降落要打开遮光板| 人在什么情况下会发烧| psp是什么意思| 文爱是什么| 2型糖尿病吃什么药降糖效果好| 突然头晕冒虚汗什么原因| 十二月八号是什么星座| 绿草如茵是什么生肖| april是什么意思| im医学上是什么意思| 乳糖不耐受吃什么药| 经常口腔溃疡吃什么药| 毛豆子炒什么好吃| 一个口四个又念什么| 武松打虎打的是什么虎| 微针有什么功效| 一千年前是什么朝代| 茶寿为什么是108岁| 狗头是什么意思| 烂大街是什么意思| 有什么书| bpo是什么| 外甥女是什么关系| 为什么女的会流水怎么回事| 头孢什么时候吃| 髋关节积液是什么原因造成的| 有口臭去医院挂什么科| 什么的月亮| 老是打喷嚏是什么原因| 肌肉萎缩吃什么药| 口腔白斑是什么病| 什么菜可以隔夜吃| 女性尿频尿急吃什么药| 菜花病是什么| 化妆水是什么| 5点至7点是什么时辰| 吃什么降尿酸最有效| 什么叫筋膜炎| 姓许的女孩取什么名字好听| 十二月四号是什么星座| 什么是单亲家庭| 低压高吃什么药最有效| 一点点奶茶什么最好喝| 什么家欢乐| 外人是什么意思| 后脑勺胀痛什么原因| 男生来大姨夫是什么意思| 脚麻木是什么原因| 梦见摘黄瓜是什么意思| 百度

法国公司签下塞尔维亚机场25年特许经营权

-- Module for converting between different representations of numbers. See talk page for user documentation.
-- For unit tests see: [[Module:ConvertNumeric/testcases]]
-- When editing, preview with: [[Module_talk:ConvertNumeric/testcases]]
-- First, edit [[Module:ConvertNumeric/sandbox]], then preview with [[Module_talk:ConvertNumeric/sandbox/testcases]]
require('strict')

local ones_position = {
	[0] = 'zero',
	[1] = 'one',
	[2] = 'two',
	[3] = 'three',
	[4] = 'four',
	[5] = 'five',
	[6] = 'six',
	[7] = 'seven',
	[8] = 'eight',
	[9] = 'nine',
	[10] = 'ten',
	[11] = 'eleven',
	[12] = 'twelve',
	[13] = 'thirteen',
	[14] = 'fourteen',
	[15] = 'fifteen',
	[16] = 'sixteen',
	[17] = 'seventeen',
	[18] = 'eighteen',
	[19] = 'nineteen'
}

local ones_position_ord = {
	[0] = 'zeroth',
	[1] = 'first',
	[2] = 'second',
	[3] = 'third',
	[4] = 'fourth',
	[5] = 'fifth',
	[6] = 'sixth',
	[7] = 'seventh',
	[8] = 'eighth',
	[9] = 'ninth',
	[10] = 'tenth',
	[11] = 'eleventh',
	[12] = 'twelfth',
	[13] = 'thirteenth',
	[14] = 'fourteenth',
	[15] = 'fifteenth',
	[16] = 'sixteenth',
	[17] = 'seventeenth',
	[18] = 'eighteenth',
	[19] = 'nineteenth'
}

local ones_position_plural = {
	[0] = 'zeros',
	[1] = 'ones',
	[2] = 'twos',
	[3] = 'threes',
	[4] = 'fours',
	[5] = 'fives',
	[6] = 'sixes',
	[7] = 'sevens',
	[8] = 'eights',
	[9] = 'nines',
	[10] = 'tens',
	[11] = 'elevens',
	[12] = 'twelves',
	[13] = 'thirteens',
	[14] = 'fourteens',
	[15] = 'fifteens',
	[16] = 'sixteens',
	[17] = 'seventeens',
	[18] = 'eighteens',
	[19] = 'nineteens'
}

local tens_position = {
	[2] = 'twenty',
	[3] = 'thirty',
	[4] = 'forty',
	[5] = 'fifty',
	[6] = 'sixty',
	[7] = 'seventy',
	[8] = 'eighty',
	[9] = 'ninety'
}

local tens_position_ord = {
	[2] = 'twentieth',
	[3] = 'thirtieth',
	[4] = 'fortieth',
	[5] = 'fiftieth',
	[6] = 'sixtieth',
	[7] = 'seventieth',
	[8] = 'eightieth',
	[9] = 'ninetieth'
}

local tens_position_plural = {
	[2] = 'twenties',
	[3] = 'thirties',
	[4] = 'forties',
	[5] = 'fifties',
	[6] = 'sixties',
	[7] = 'seventies',
	[8] = 'eighties',
	[9] = 'nineties'
}

local groups = {
	[1] = 'thousand',
	[2] = 'million',
	[3] = 'billion',
	[4] = 'trillion',
	[5] = 'quadrillion',
	[6] = 'quintillion',
	[7] = 'sextillion',
	[8] = 'septillion',
	[9] = 'octillion',
	[10] = 'nonillion',
	[11] = 'decillion',
	[12] = 'undecillion',
	[13] = 'duodecillion',
	[14] = 'tredecillion',
	[15] = 'quattuordecillion',
	[16] = 'quindecillion',
	[17] = 'sexdecillion',
	[18] = 'septendecillion',
	[19] = 'octodecillion',
	[20] = 'novemdecillion',
	[21] = 'vigintillion',
	[22] = 'unvigintillion',
	[23] = 'duovigintillion',
	[24] = 'tresvigintillion',
	[25] = 'quattuorvigintillion',
	[26] = 'quinquavigintillion',
	[27] = 'sesvigintillion',
	[28] = 'septemvigintillion',
	[29] = 'octovigintillion',
	[30] = 'novemvigintillion',
	[31] = 'trigintillion',
	[32] = 'untrigintillion',
	[33] = 'duotrigintillion',
	[34] = 'trestrigintillion',
	[35] = 'quattuortrigintillion',
	[36] = 'quinquatrigintillion',
	[37] = 'sestrigintillion',
	[38] = 'septentrigintillion',
	[39] = 'octotrigintillion',
	[40] = 'noventrigintillion',
	[41] = 'quadragintillion',
	[51] = 'quinquagintillion',
	[61] = 'sexagintillion',
	[71] = 'septuagintillion',
	[81] = 'octogintillion',
	[91] = 'nonagintillion',
	[101] = 'centillion',
	[102] = 'uncentillion',
	[103] = 'duocentillion',
	[104] = 'trescentillion',
	[111] = 'decicentillion',
	[112] = 'undecicentillion',
	[121] = 'viginticentillion',
	[122] = 'unviginticentillion',
	[131] = 'trigintacentillion',
	[141] = 'quadragintacentillion',
	[151] = 'quinquagintacentillion',
	[161] = 'sexagintacentillion',
	[171] = 'septuagintacentillion',
	[181] = 'octogintacentillion',
	[191] = 'nonagintacentillion',
	[201] = 'ducentillion',
	[301] = 'trecentillion',
	[401] = 'quadringentillion',
	[501] = 'quingentillion',
	[601] = 'sescentillion',
	[701] = 'septingentillion',
	[801] = 'octingentillion',
	[901] = 'nongentillion',
	[1001] = 'millinillion',
}

local roman_numerals = {
	I = 1,
	V = 5,
	X = 10,
	L = 50,
	C = 100,
	D = 500,
	M = 1000
}

local engord_tens_end  = {
	['twentieth']	= 20,
	['thirtieth']	= 30,
	['fortieth']	= 40,
	['fiftieth']	= 50,
	['sixtieth']	= 60,
	['seventieth']	= 70,
	['eightieth']	= 80,
	['ninetieth']	= 90,
}

local eng_tens_cont = {
	['twenty']	= 20,
	['thirty']	= 30,
	['forty']	= 40,
	['fifty']	= 50,
	['sixty']	= 60,
	['seventy']	= 70,
	['eighty']	= 80,
	['ninety']	= 90,
}

-- 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)
	if type(roman) ~= "string" then return -1, "roman numeral not a string" end
	local rev = roman:reverse()
	local raising = true
	local last = 0
	local result = 0
	for i = 1, #rev do
		local c = rev:sub(i, i)
		local next = roman_numerals[c]
		if next == nil then return -1, "roman numeral contains illegal character " .. c end
		if next > last then
			result = result + next
			raising = true
		elseif next < last then
			result = result - next
			raising = false
		elseif raising then
			result = result + next
		else
			result = result - next
		end
		last = next
	end
	return result
end

-- 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 terminal_ones, terminal_tens
	if ordinal then
		terminal_ones = ones_position_ord
		terminal_tens = tens_position_ord
	elseif plural then
		terminal_ones = ones_position_plural
		terminal_tens = tens_position_plural
	else
		terminal_ones = ones_position
		terminal_tens = tens_position
	end

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

local function standard_suffix(ordinal, plural)
	if ordinal then return 'th' end
	if plural then return 's' end
	return ''
end

-- 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)
	num = tonumber(num)
	if num < 100 then
		return numeral_to_english_less_100(num, ordinal, plural, zero)
	elseif num % 100 == 0 then
		return ones_position[num/100] .. ' hundred' .. standard_suffix(ordinal, plural)
	else
		return ones_position[math.floor(num/100)] .. ' hundred ' .. (use_and and 'and ' or '') .. numeral_to_english_less_100(num % 100, ordinal, plural, zero)
	end
end

-- 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 eng = string.lower(english or '')

	local engord_lt20 = {} -- ones_position_ord{} keys & values swapped
	for k, v in pairs( ones_position_ord ) do
		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
		return eng_lt20[eng] -- e.g. one -> 1
	elseif eng_tens_cont[eng] then
		return eng_tens_cont[eng] -- e.g. ninety -> 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  = eng_lt20[ones]
			if tens_cont and ones_end then
				return tens_cont + ones_end -- e.g. ninety-nine -> 99
			end
		end
	end
	return -1 -- Failed
end

-- Converts a number expressed as a string in scientific notation to a string in standard decimal notation
-- e.g. 1.23E5 -> 123000, 1.23E-5 = .0000123. Conversion is exact, no rounding is performed.
local function scientific_notation_to_decimal(num)
	local exponent, subs = num:gsub("^%-?%d*%.?%d*%-?[Ee]([+%-]?%d+)$", "%1")
	if subs == 0 then return num end  -- Input not in scientific notation, just return unmodified
	exponent = tonumber(exponent)

	local negative = num:find("^%-")
	local _, decimal_pos = num:find("%.")
	-- Mantissa will consist of all decimal digits with no decimal point
	local mantissa = num:gsub("^%-?(%d*)%.?(%d*)%-?[Ee][+%-]?%d+$", "%1%2")
	if negative and decimal_pos then decimal_pos = decimal_pos - 1 end
	if not decimal_pos then decimal_pos = #mantissa + 1 end

	-- Remove leading zeros unless decimal point is in first position
	while decimal_pos > 1 and mantissa:sub(1,1) == '0' do
		mantissa = mantissa:sub(2)
		decimal_pos = decimal_pos - 1
	end
	-- Shift decimal point right for exponent > 0
	while exponent > 0 do
		decimal_pos = decimal_pos + 1
		exponent = exponent - 1
		if decimal_pos > #mantissa + 1 then mantissa = mantissa .. '0' end
		-- Remove leading zeros unless decimal point is in first position
		while decimal_pos > 1 and mantissa:sub(1,1) == '0' do
			mantissa = mantissa:sub(2)
			decimal_pos = decimal_pos - 1
		end
	end
	-- Shift decimal point left for exponent < 0
	while exponent < 0 do
		if decimal_pos == 1 then
			mantissa = '0' .. mantissa
		else
			decimal_pos = decimal_pos - 1
		end
		exponent = exponent + 1
	end

	-- Insert decimal point in correct position and return
	return (negative and '-' or '') .. mantissa:sub(1, decimal_pos - 1) .. '.' .. mantissa:sub(decimal_pos)
end

-- Rounds a number to the nearest integer (NOT USED)
local function round_num(x)
	if x%1 >= 0.5 then
		return math.ceil(x)
	else
		return math.floor(x)
	end
end

-- 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.
-- Larger numbers will be rounded to a number with only one nonzero digit in front and all other digits zero.
-- Negative sign is preserved and does not count towards word limit.
local function round_for_english(num, round)
	-- If an integer with at most two digits, just return
	if num:find("^%-?%d?%d%.?$") then return num end

	local negative = num:find("^%-")
	if negative then
		-- We're rounding magnitude so flip it
		if round == 'up' then round = 'down' elseif round == 'down' then round = 'up' end
	end

	-- If at most two digits before decimal, round to integer and return
	local _, _, small_int, trailing_digits, round_digit = num:find("^%-?(%d?%d?)%.((%d)%d*)$")
	if small_int then
		if small_int == '' then small_int = '0' end
		if (round == 'up' and trailing_digits:find('[1-9]')) or (round == 'on' and tonumber(round_digit) >= 5) then
			small_int = tostring(tonumber(small_int) + 1)
		end
		return (negative and '-' or '') .. small_int
	end

	-- When rounding up, any number with > 1 nonzero digit will round up (e.g. 1000000.001 rounds up to 2000000)
	local nonzero_digits = 0
	for digit in num:gfind("[1-9]") do
		nonzero_digits = nonzero_digits + 1
	end

	num = num:gsub("%.%d*$", "") -- Remove decimal part
	-- Second digit used to determine which way to round lead digit
	local _, _, lead_digit, round_digit, round_digit_2, rest = num:find("^%-?(%d)(%d)(%d)(%d*)$")
	if tonumber(lead_digit .. round_digit) < 20 and (1 + #rest) % 3 == 0 then
		-- In English numbers < 20 are one word so put 2 digits in lead and round based on 3rd
		lead_digit = lead_digit .. round_digit
		round_digit = round_digit_2
	else
		rest = round_digit_2 .. rest
	end

	if (round == 'up' and nonzero_digits > 1) or (round == 'on' and tonumber(round_digit) >= 5) then
		lead_digit = tostring(tonumber(lead_digit) + 1)
	end
	-- All digits but lead digit will turn to zero
	rest = rest:gsub("%d", "0")
	return (negative and '-' or '') .. lead_digit .. '0' .. rest
end

local denominators = {
	[2] = { 'half', plural = 'halves' },
	[3] = { 'third' },
	[4] = { 'quarter', us = 'fourth' },
	[5] = { 'fifth' },
	[6] = { 'sixth' },
	[8] = { 'eighth' },
	[9] = { 'ninth' },
	[10] = { 'tenth' },
	[16] = { 'sixteenth' },
}

-- Return status, fraction where:
-- status is a string:
--     "finished" if there is a fraction with no whole number;
--     "ok" if fraction is empty or valid;
--     "unsupported" if bad fraction;
-- fraction is a string giving (numerator / denominator) as English text, or is "".
-- Only unsigned fractions with a very limited range of values are supported,
-- except that if whole is empty, the numerator can use "-" to indicate negative.
-- whole (string or nil): nil or "" if no number before the fraction
-- numerator (string or nil): numerator, if any (default = 1 if a denominator is given)
-- denominator (string or nil): denominator, if any
-- sp_us (boolean): true if sp=us
-- negative_word (string): word to use for negative sign, if whole is empty
-- use_one (boolean): false: 2+1/2 → "two and a half"; true: "two and one-half"
local function fraction_to_english(whole, numerator, denominator, sp_us, negative_word, use_one)
	if numerator or denominator then
		local finished = (whole == nil or whole == '')
		local sign = ''
		if numerator then
			if finished and numerator:sub(1, 1) == '-' then
				numerator = numerator:sub(2)
				sign = negative_word .. ' '
			end
		else
			numerator = '1'
		end
		if not numerator:match('^%d+$') or not denominator or not denominator:match('^%d+$') then
			return 'unsupported', ''
		end
		numerator = tonumber(numerator)
		denominator = tonumber(denominator)
		local dendata = denominators[denominator]
		if not (dendata and 1 <= numerator and numerator <= 99) then
			return 'unsupported', ''
		end
		local numstr, denstr
		local sep = '-'
		if numerator == 1 then
			denstr = sp_us and dendata.us or dendata[1]
			if finished or use_one then
				numstr = 'one'
			elseif denstr:match('^[aeiou]') then
				numstr = 'an'
				sep = ' '
			else
				numstr = 'a'
				sep = ' '
			end
		else
			numstr = numeral_to_english_less_100(numerator)
			denstr = dendata.plural
			if not denstr then
				denstr = (sp_us and dendata.us or dendata[1]) .. 's'
			end
		end
		if finished then
			return 'finished', sign .. numstr .. sep .. denstr
		end
		return 'ok', ' and ' .. numstr .. sep .. denstr
	end
	return 'ok', ''
end

-- Takes a decimal number and converts it to English text.
-- Return nil if a fraction cannot be converted (only some numbers are supported for fractions).
-- num (string or nil): the number to convert.
--      Can be an arbitrarily large decimal, such as "-123456789123456789.345", and
--      can use scientific notation (e.g. "1.23E5").
--      May fail for very large numbers not listed in "groups" such as "1E4000".
--      num is nil if there is no whole number before a fraction.
-- numerator (string or nil): numerator of fraction (nil if no fraction)
-- denominator (string or nil): denominator of fraction (nil if no fraction)
-- 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
-- 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')
-- plural (boolean): whether to pluralize the resulting number
-- links: nil: do not add any links; 'on': link "billion" and larger to Orders of magnitude article;
--        any other text: list of numbers to link (e.g. "billion,quadrillion")
-- negative_word: word to use for negative sign (typically 'negative' or 'minus'; nil to use default)
-- round: nil or '': no rounding; 'on': round to nearest two-word number; 'up'/'down': round up/down to two-word number
-- zero: word to use for value '0' (nil to use default)
-- use_one (boolean): false: 2+1/2 → "two and a half"; true: "two and one-half"
local function _numeral_to_english(num, numerator, denominator, capitalize, use_and, hyphenate, ordinal, plural, links, negative_word, round, zero, use_one)
	if not negative_word then
		if use_and then
			-- TODO Should 'minus' be used when do not have sp=us?
			--      If so, need to update testcases, and need to fix "minus zero".
			-- negative_word = 'minus'
			negative_word = 'negative'
		else
			negative_word = 'negative'
		end
	end
	local status, fraction_text = fraction_to_english(num, numerator, denominator, not use_and, negative_word, use_one)
	if status == 'unsupported' then
		return nil
	end
	if status == 'finished' then
		-- Input is a fraction with no whole number.
		-- Hack to avoid executing stuff that depends on num being a number.
		local s = fraction_text
		if hyphenate then s = s:gsub("%s", "-") end
		if capitalize then s = s:gsub("^%l", string.upper) end
		return s
	end
	num = scientific_notation_to_decimal(num)
	if round and round ~= '' then
		if round ~= 'on' and round ~= 'up' and round ~= 'down' then
			error("Invalid rounding mode")
		end
		num = round_for_english(num, round)
	end

	-- Separate into negative sign, num (digits before decimal), decimal_places (digits after decimal)
	local MINUS = '?'  -- Unicode U+2212 MINUS SIGN (may be in values from [[Module:Convert]])
	if num:sub(1, #MINUS) == MINUS then
		num = '-' .. num:sub(#MINUS + 1)  -- replace MINUS with '-'
	elseif num:sub(1, 1) == '+' then
		num = num:sub(2)  -- ignore any '+'
	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

	-- For each group of 3 digits except the last one, print with appropriate group name (e.g. million)
	local s = ''
	while #num > 3 do
		if s ~= '' then s = s .. ' ' end
		local group_num = math.floor((#num - 1) / 3)
		local group = groups[group_num]
		local group_digits = #num - group_num*3
		s = s .. numeral_to_english_less_1000(num:sub(1, group_digits), false, false, false, zero) .. ' '
		if links and (((links == 'on' and group_num >= 3) or links:find(group)) and group_num <= 13) then
			s = s .. '[[Orders_of_magnitude_(numbers)#10' .. group_num*3 .. '|' .. group .. ']]'
		else
			s = s .. group
		end
		num = num:sub(1 + group_digits)
		num = num:gsub("^0*", "")  -- Trim leading zeros
	end

	-- Handle final three digits of integer part
	if s ~= '' and num ~= '' then
		if #num <= 2 and use_and then
			s = s .. ' and '
		else
			s = s .. ' '
		end
	end
	if s == '' or num ~= '' then
		s = s .. numeral_to_english_less_1000(num, use_and, ordinal, plural, zero)
	elseif ordinal or plural then
		-- Round numbers like "one million" take standard suffixes for ordinal/plural
		s = s .. standard_suffix(ordinal, plural)
	end

	-- For decimal places (if any) output "point" followed by spelling out digit by digit
	if decimal_places then
		s = s .. ' point'
		for i = 1, #decimal_places do
			s = s .. ' ' .. ones_position[tonumber(decimal_places:sub(i,i))]
		end
	end

	s = s:gsub("^%s*(.-)%s*$", "%1")   -- Trim whitespace
	if ordinal and plural then s = s .. 's' end  -- s suffix works for all ordinals
	if negative and s ~= zero then s = negative_word .. ' ' .. s end
	s = s:gsub("negative zero", "zero")
	s = s .. fraction_text
	if hyphenate then s = s:gsub("%s", "-") end
	if capitalize then s = s:gsub("^%l", string.upper) end
	return s
end

local function _numeral_to_english2(args)
	local num = tostring(args.num)

	num = num:gsub("^%s*(.-)%s*$", "%1")   -- Trim whitespace
	num = num:gsub(",", "")   -- Remove commas
	num = num:gsub("^<span[^<>]*></span>", "") -- Generated by Template:age
	if num ~= '' then  -- a fraction may have an empty whole number
		if not num:find("^%-?%d*%.?%d*%-?[Ee]?[+%-]?%d*$") then
			-- Input not in a valid format, try to eval it as an expr to see
			-- if that produces a number (e.g. "3 + 5" will become "8").
			local noerr, result = pcall(mw.ext.ParserFunctions.expr, num)
			if noerr then
				num = result
			end
		end
	end

	-- Call helper function passing args
	return _numeral_to_english(
		num,
		args['numerator'],
		args['denominator'],
		args['capitalize'],
		args['use_and'],
		args['hyphenate'],
		args['ordinal'],
		args['plural'],
		args['links'],
		args['negative_word'],
		args['round'],
		args['zero'],
		args['use_one']
	) or ''
end

local p = {  -- Functions that can be called from another module
	roman_to_numeral = roman_to_numeral,
	spell_number = _numeral_to_english,
	spell_number2 = _numeral_to_english2,
	english_to_ordinal = english_to_ordinal,
	english_to_numeral = english_to_numeral,
}

function p._roman_to_numeral(frame) -- Callable via {{#invoke:ConvertNumeric|_roman_to_numeral|VI}}
	return roman_to_numeral(frame.args[1])
end

function p._english_to_ordinal(frame) -- callable via {{#invoke:ConvertNumeric|_english_to_ordinal|First}}
	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

function p.numeral_to_english(frame)
	local args = frame.args
	-- Tail call to helper function passing args from frame
	return _numeral_to_english2{
		['num'] = args[1],
		['numerator'] = args['numerator'],
		['denominator'] = args['denominator'],
		['capitalize'] = args['case'] == 'U' or args['case'] == 'u',
		['use_and'] = args['sp'] ~= 'us',
		['hyphenate'] = args['adj'] == 'on',
		['ordinal'] = args['ord'] == 'on',
		['plural'] = args['pl'] == 'on',
		['links'] = args['lk'],
		['negative_word'] = args['negative'],
		['round'] = args['round'],
		['zero'] = args['zero'],
		['use_one'] = args['one'] == 'one'  -- experiment: using '|one=one' makes fraction 2+1/2 give "two and one-half" instead of "two and a half"
	}
end

---- recursive function for p.decToHex
local function decToHexDigit(dec)
	local dig = {"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"}
	local div = math.floor(dec/16)
	local mod = dec-(16*div)
	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

---- finds all the decimal numbers in the input text and hexes each of them
function p.decToHex(frame)
	local args=frame.args
	local parent=frame.getParent(frame)
	local pargs={}
	if parent then pargs=parent.args end
	local text=args[1] or pargs[1] or ""
	local minlength=args.minlength or pargs.minlength or 1
	minlength=tonumber(minlength)
	local prowl=mw.ustring.gmatch(text,"(.-)(%d+)")
	local output=""
	repeat
		local chaff,dec=prowl()
		if not(dec) then break end
		local hex=decToHexDigit(dec)
		while (mw.ustring.len(hex)<minlength) do hex="0"..hex end
		output=output..chaff..hex
	until false
	local chaff=mw.ustring.match(text,"(%D+)$") or ""
	return output..chaff
end

return p
民考民是什么意思 百年好合什么意思 下巴长硬包是什么原因 淋巴细胞比率偏高是什么意思 司令员是什么军衔
十月二十九是什么星座 痰湿体质吃什么食物好 血虚吃什么食物可以补 痔疮是什么样的 刀鱼和带鱼有什么区别
吃什么可以生精最快 不适是什么意思 植发用什么头发 2003年属什么生肖 谭咏麟属什么生肖
斯里兰卡说什么语言 检查是否怀孕要挂什么科 西洋参吃多了有什么副作用 特需门诊和专家门诊有什么区别 血压低吃什么补得快
生物科技是做什么的chuanglingweilai.com 智齿什么时候开始长hcv9jop3ns1r.cn 什么自如hcv8jop1ns3r.cn 狸猫是什么猫zhongyiyatai.com 胖大海和什么搭配最好hcv8jop8ns3r.cn
什么是经络hcv9jop7ns1r.cn 彼岸花又叫什么花hcv9jop5ns2r.cn 传染病4项是什么hcv8jop7ns3r.cn 芸字五行属什么kuyehao.com 分开后我会笑着说是什么歌hcv7jop4ns8r.cn
o型血和什么血型最配hcv7jop6ns7r.cn 医院点痣挂什么科hcv8jop4ns6r.cn 长期服用丙戊酸钠有什么副作用hanqikai.com 梦见抓鱼是什么预兆hcv9jop0ns3r.cn 身体湿气重吃什么药hcv7jop5ns3r.cn
二甲医院是什么级别hcv8jop8ns6r.cn 益生菌什么时间段吃效果好hcv8jop8ns0r.cn 舌苔厚腻吃什么中成药hcv7jop6ns9r.cn 沙土地适合种什么农作物hcv8jop5ns8r.cn 钟字五行属什么hcv8jop4ns9r.cn
百度