Перейти к содержанию
Главное меню
Главное меню
переместить в боковую панель
скрыть
Навигация
Заглавная страница
Указатели
Свежие правки
Случайная страница
Справка по MediaWiki
Народные Сказки
Поиск
Найти
Создать учётную запись
Войти
Персональные инструменты
Создать учётную запись
Войти
Страницы для неавторизованных редакторов
узнать больше
Вклад
Обсуждение
Редактирование:
Модуль:Math
Модуль
Обсуждение
English
Читать
Править код
История
Инструменты
Инструменты
переместить в боковую панель
скрыть
Действия
Читать
Править код
История
Общие
Ссылки сюда
Связанные правки
Служебные страницы
Сведения о странице
Внимание:
Вы не вошли в систему. Ваш IP-адрес будет общедоступен, если вы запишете какие-либо изменения. Если вы
войдёте
или
создадите учётную запись
, её имя будет использоваться вместо IP-адреса, наряду с другими преимуществами.
Анти-спам проверка.
Не
заполняйте это!
--[[ This module provides a number of basic mathematical operations. ]] local z = {} -- Generate random number function z.random( frame ) first = tonumber(frame.args[1]) -- if it doesn't exist it's NaN, if not a number it's nil second = tonumber(frame.args[2]) if first then -- if NaN or nil, will skip down to final return if first <= second then -- could match if both nil, but already checked that first is a number in last line return math.random(first, second) end return math.random(first) end return math.random() end --[[ order Determine order of magnitude of a number Usage: {{#invoke: Math | order | value }} ]] function z.order(frame) local input_string = (frame.args[1] or frame.args.x or '0'); local input_number; input_number = z._cleanNumber( frame, input_string ); if input_number == nil then return '<strong class="error">Ошибка формата данных: нечисловое входное значение при определении десятичной степени</strong>' else return z._order( input_number ) end end function z._order(x) if x == 0 then return 0 end return math.floor(math.log10(math.abs(x))) end --[[ precision Detemines the precision of a number using the string representation Usage: {{ #invoke: Math | precision | value }} ]] function z.precision( frame ) local input_string = (frame.args[1] or frame.args.x or '0'); local trap_fraction = frame.args.check_fraction or false; local input_number; if type( trap_fraction ) == 'string' then trap_fraction = trap_fraction:lower(); if trap_fraction == 'false' or trap_fraction == '0' or trap_fraction == 'no' or trap_fraction == '' then trap_fraction = false; else trap_fraction = true; end end if trap_fraction then local pos = string.find( input_string, '/', 1, true ); if pos ~= nil then if string.find( input_string, '/', pos + 1, true ) == nil then local denominator = string.sub( input_string, pos+1, -1 ); local denom_value = tonumber( denominator ); if denom_value ~= nil then return math.log10(denom_value); end end end end input_number, input_string = z._cleanNumber( frame, input_string ); if input_string == nil then return '<strong class="error">Ошибка формата данных: нечисловое входное значение при определении дробной части</strong>' else return z._precision( input_string ) end end function z._precision( x ) x = string.upper( x ) local decimal = string.find( x, '[.,]', 1 ) local exponent_pos = string.find( x, 'E', 1, true ) local result = 0; if exponent_pos ~= nil then local exponent = string.sub( x, exponent_pos + 1 ) x = string.sub( x, 1, exponent_pos - 1 ) result = result - tonumber( exponent ) end if decimal ~= nil then result = result + string.len( x ) - decimal return result end local pos = string.len( x ); while x:byte(pos) == string.byte('0') do pos = pos - 1 result = result - 1 if pos <= 0 then return 0 end end return result end --[[ max Finds the maximum argument Usage: {{#invoke:Math| max | value1 | value2 | ... }} OR {{#invoke:Math| max }} When used with no arguments, it takes its input from the parent frame. Note, any values that do not evaluate to numbers are ignored. ]] function z.max( frame ) local args = frame.args; if args[1] == nil then local parent = frame:getParent(); args = parent.args; end local max_value = nil; local i = 1; while args[i] ~= nil do local val = z._cleanNumber( frame, args[i] ); if val ~= nil then if max_value == nil or val > max_value then max_value = val; end end i = i + 1; end return max_value end --[[ min Finds the minimum argument Usage: {{#invoke:Math| min | value1 | value2 | ... }} OR {{#invoke:Math| min }} When used with no arguments, it takes its input from the parent frame. Note, any values that do not evaluate to numbers are ignored. ]] function z.min( frame ) local args = frame.args; if args[1] == nil then local parent = frame:getParent(); args = parent.args; end local min_value = nil; local i = 1; while args[i] ~= nil do local val = z._cleanNumber( frame, args[i] ); if val ~= nil then if min_value == nil or val < min_value then min_value = val; end end i = i + 1; end return min_value end --[[ round Rounds a number to specified precision Usage: {{#invoke:Math | round | value | precision }} --]] function z.round(frame) local value, precision; value = z._cleanNumber( frame, frame.args[1] or frame.args.value or 0 ); precision = z._cleanNumber( frame, frame.args[2] or frame.args.precision or 0 ); if value == nil or precision == nil then return '<strong class="error">Ошибка формата данных: нечисловое входное значение при округлении до целого</strong>' else return z._round( value, precision ); end end function z._round( value, precision ) local rescale = math.pow( 10, precision ); return math.floor( value * rescale + 0.5 ) / rescale; end --[[ precision_format Rounds a number to the specified precision and formats according to rules originally used for {{template:Rnd}}. Output is a string. Usage: {{#invoke: Math | precision_format | number | precision }} ]] function z.precision_format(args) local value_string = args[1] or 0 local precision = args[2] or 0 return z._precision_format(value_string, precision) end function z._cleanNumberNew( number_string ) if type(number_string) == 'number' then -- We were passed a number, so we don't need to do any processing. return number_string, tostring(number_string) elseif type(number_string) ~= 'string' or not number_string:find('%S') then -- We were passed a non-string or a blank string, so exit. return nil, nil; end -- Attempt basic conversion local number = tonumber(number_string) -- If failed, attempt to evaluate input as an expression if number == nil then local success, result = pcall(mw.ext.ParserFunctions.expr, number_string) if success then number = tonumber(result) number_string = tostring(number) else number = nil number_string = nil end else number_string = number_string:match("^%s*(.-)%s*$") -- String is valid but may contain padding, clean it. number_string = number_string:match("^%+(.*)$") or number_string -- Trim any leading + signs. if number_string:find('^%-?0[xX]') then -- Number is using 0xnnn notation to indicate base 16; use the number that Lua detected instead. number_string = tostring(number) end end return number, number_string end function z._precision_format(value_string, precision) -- For access to Mediawiki built-in formatter. local lang = mw.getContentLanguage(); local r = "before: v = " .. tostring(value_string) .. "; p= " .. tostring(precision) .. '\n' local value value, value_string = z._cleanNumberNew(value_string) precision = z._cleanNumberNew(precision) -- Check for non-numeric input if value == nil or precision == nil then return '<strong class="error">Ошибка формата данных: нечисловое входное значение при округлении с заданной точностью</strong>' end local current_precision = z._precision(value) local order = z._order(value) -- Due to round-off effects it is neccesary to limit the returned precision under -- some circumstances because the terminal digits will be inaccurately reported. if order + precision >= 14 then local orig_precision = z._precision(value_string) if order + orig_precision >= 14 then precision = 13 - order; end end -- If rounding off, truncate extra digits if precision < current_precision then value = z._round(value, precision) current_precision = z._precision(value) end local formatted_num = lang:formatNum(math.abs(value)) local sign -- Use proper unary minus sign rather than ASCII default if value < 0 then sign = '−' else sign = '' end -- Handle cases requiring scientific notation if string.find(formatted_num, 'E', 1, true) ~= nil or math.abs(order) >= 9 then value = value * math.pow(10, -order) current_precision = current_precision + order precision = precision + order formatted_num = lang:formatNum(math.abs(value)) else order = 0; end formatted_num = sign .. formatted_num -- Pad with zeros, if needed if current_precision < precision then local padding if current_precision <= 0 then if precision > 0 then local zero_sep = lang:formatNum(1.1) formatted_num = formatted_num .. zero_sep:sub(2,2) padding = precision if padding > 20 then padding = 20 end formatted_num = formatted_num .. string.rep('0', padding) end else padding = precision - current_precision if padding > 20 then padding = 20 end formatted_num = formatted_num .. string.rep('0', padding) end end -- Add exponential notation, if necessary. if order ~= 0 then -- Use proper unary minus sign rather than ASCII default if order < 0 then order = '−' .. lang:formatNum(math.abs(order)) else order = lang:formatNum(order) end formatted_num = formatted_num .. '<span style="margin:0 .15em 0 .25em">×</span>10<sup>' .. order .. '</sup>' end return formatted_num end --[[ Helper function that interprets the input numerically. If the input does not appear to be a number, attempts evaluating it as a parser functions expression. ]] function z._cleanNumber( frame, number_string ) if number_string == nil or number_string:len() == 0 then return nil, nil; end -- Attempt basic conversion local number = tonumber( number_string ) -- If failed, attempt to evaluate input as an expression if number == nil then local attempt = frame:callParserFunction( '#expr', number_string ); attempt = tonumber( attempt ); if attempt ~= nil then number = attempt; number_string = tostring( number ); else number = nil; number_string = nil; end else -- String is valid but may contain padding, clean it. number_string = mw.text.trim(number_string) end return number, number_string; end local function roman(i) local w, t, val, let = {}, { {1000, "M"}, {900, "CM"}, {500, "D"}, {400, "CD"}, {100, "C"}, {90, "XC"}, {50, "L"}, {40, "XL"}, {10, "X"}, {9, "IX"}, {5, "V"}, {4, "IV"}, {1, "I"} } for n, v in ipairs(t) do val, let = unpack(v) w[n]=string.rep(let,i/val) i=i % val end return table.concat(w) end function z.Roman(frame) -- Преобразует числа от 1 до 4999999 в римские local function try_tonumber(a) return math.floor(tonumber(a) or error('\''.. a ..'\' не является числом.')); end local str = frame.args[1] or ''; if str == '' then -- пустой параметр return str; end local r, N = pcall(try_tonumber, str); -- попытка преобразовать в число if r then if N<1 or N>=5e6 then return frame.args[2] or 'N/A' end local R=N%5000 N=(N-R)/1000 return (N>0 and table.concat{'<span style="text-decoration:overline;">',roman(N),'</span>'} or '')..roman(R) else return '<strong class="error">' .. N .. '</strong>'; -- вывод ошибки end end function z.RussianFem(frame) local result = z.Russian(frame) return string.gsub(string.gsub(result, 'два$', 'две'), 'один$', 'одна') end --[[ Выводит числа прописью на русском ]] function z.Russian(frame) local str = frame.args[1] or ''; if str == '' then return ''; end local lang = mw.getLanguage( 'ru' ) if string.find(str, '%.') or string.find(str, ',') then a, b = string.match(str, '(%d+).(%d+)') local basic = { 'десят', 'сот'} local prefixes = {'', 'десяти', 'сто'} local orders = {'тысячн', 'миллионн', 'миллиардн', 'триллионн', 'квадриллионн'} local ed = {'ая', 'ые', 'ых'} a = #a and a or '0' b = #b and b or '0' local order = math.floor(#b / #prefixes) if order > #orders then order = #orders b = string.sub(b, 0, #prefixes * #orders) end mw.log(order) local ia = z.RussianFem({args={a}}) local ib = z.RussianFem({args={b}}) local intgr = 'цел' local fract = '' if order == 0 then fract = basic[#b] else fract = prefixes[#b % #prefixes + 1] .. orders[order] end intgr = lang:plural(tonumber(a, 10) % 1000, intgr .. ed[1], intgr .. ed[2], intgr .. ed[3]) fract = lang:plural(tonumber(b, 10) % 1000, fract .. ed[1], fract .. ed[2], fract .. ed[3]) return ia .. ' ' .. intgr .. ' и ' .. ib .. ' ' .. fract end local number = tonumber( str, 10 ) local zero = 'ноль' local ones = { 'один', 'два', 'три', 'четыре', 'пять', 'шесть', 'семь', 'восемь', 'девять', 'десять', 'одиннадцать', 'двенадцать', 'тринадцать', 'четырнадцать', 'пятнадцать', 'шестнадцать', 'семнадцать', 'восемнадцать', 'девятнадцать' } local tens = { '', 'двадцать', 'тридцать', 'сорок', 'пятьдесят', 'шестьдесят', 'семьдесят', 'восемьдесят', 'девяносто' } local hundreds = { 'сто', 'двести', 'триста', 'четыреста', 'пятьсот', 'шестьсот', 'семьсот', 'восемьсот', 'девятьсот' } local unitsPlural = { { '', '', '' }, { 'тысяча', 'тысячи', 'тысяч' }, { 'миллион', 'миллиона', 'миллионов' }, { 'миллиард', 'миллиарда', 'миллиардов' }, { 'триллион', 'триллиона', 'триллионов' }, } local out = '' local outMinus = '' if ( number < 0 ) then outMinus = 'минус ' number = math.abs( number ) end local tripletPos = 0 while ( number > 0 ) do local triplet = number % 1000 number = math.floor( number / 1000 ) tripletPos = tripletPos + 1 if ( tripletPos > 5 ) then return '' end local tripletStr = '' local tripletUnit = '' if ( triplet > 0 ) then local unitPlural = unitsPlural[ tripletPos ] tripletUnit = lang:plural( triplet, unitPlural[1], unitPlural[2], unitPlural[3] ) end if ( triplet >= 100 ) then tripletStr = hundreds[ math.floor( triplet / 100 ) ] triplet = triplet % 100 end if ( triplet >= 20 ) then tripletStr = tripletStr .. ' ' .. tens[ math.floor( triplet / 10 ) ] triplet = triplet % 10 end if ( triplet >= 1 ) then tripletStr = tripletStr .. ' ' .. ones[ triplet ] end -- две тысячи if ( tripletPos == 2 ) then tripletStr = mw.ustring.gsub( tripletStr, 'один$', 'одна' ) tripletStr = mw.ustring.gsub( tripletStr, 'два$', 'две' ) end out = tripletStr .. ' ' .. tripletUnit .. ' ' .. out end if ( out == '' ) then out = zero end out = outMinus .. out out = mw.ustring.gsub( out, ' +', ' ' ) out = mw.text.trim ( out ) return out end return z
Описание изменений:
Пожалуйста, учтите, что любой ваш вклад в проект «Народные Сказки» может быть отредактирован или удалён другими участниками. Если вы не хотите, чтобы кто-либо изменял ваши тексты, не помещайте их сюда.
Вы также подтверждаете, что являетесь автором вносимых дополнений, или скопировали их из источника, допускающего свободное распространение и изменение своего содержимого (см.
РуСказки:Авторские права
).
НЕ РАЗМЕЩАЙТЕ БЕЗ РАЗРЕШЕНИЯ ОХРАНЯЕМЫЕ АВТОРСКИМ ПРАВОМ МАТЕРИАЛЫ!
Отменить
Справка по редактированию
(в новом окне)
Отобразить/Скрыть ограниченную ширину содержимого