ماڊيول:Math
| هي سانچو ھزارين صفحن تي استعمال ٿئي ٿو. وڏي پيماني تي خلل ۽ غير ضروري سرور لوڊ کان بچڻ لاءِ، هن سانچي ۾ ڪا به تبديلي ڪرڻ کان اڳ ان کي پهريان ان جي /sandbox يا /testcases ذيلي صفحن ۾ آزمائي ڏسو، يا پنهنجي يوزر اسپيس ۾. آزمائشي تبديليون پوءِ هڪ ئي ترميم سان هن صفحي ۾ شامل ڪري سگهجن ٿيون۔ مهرباني ڪري تبديليون لاڳو ڪرڻ کان اڳ بحث صفحي تي انهن بابت ڳالهه ٻولهه ڪرڻ تي غور ڪريو۔ |
| This module depends on the following other modules: |
هي ماڊيول ڪيترائي رياضيائي فنڪشن مهيا ڪري ٿو۔ اهي فنڪشن {{#invoke}} ذريعي يا ٻين Lua ماڊيولن مان استعمال ڪري سگهجن ٿا۔
ٻين Lua ماڊيولن مان استعمال
[سنواريو]عام وڪي صفحن مان هن ماڊيول کي استعمال ڪرڻ لاءِ ڪا خاص تياري ضروري ناهي۔ جيڪڏهن توهان هن ماڊيول کي ڪنهن ٻئي Lua ماڊيول مان استعمال ڪري رهيا آهيو ته پهرين ان کي هن طرح لوڊ ڪرڻو پوندو:
local mm = require('Module:Math')
(هتي mm جو مطلب Module Math آهي؛ جيڪڏهن چاهيو ته توهان وڌيڪ وضاحتي نالو به استعمال ڪري سگهو ٿا۔)
ماڊيول جا گهڻا فنڪشن ٻه نسخا رکن ٿا: هڪ Lua لاءِ ۽ ٻيو {{#invoke}} لاءِ۔ Lua ماڊيولن مان {{#invoke}} فنڪشن به استعمال ڪري سگهجن ٿا، پر Lua فنڪشن استعمال ڪرڻ جو فائدو اهو آهي ته توهان کي Lua جي frame object تائين رسائي جي ضرورت نه پوندي۔
Lua فنڪشنن جي نالن جي شروعات _ سان ٿيندي آهي، جڏهن ته {{#invoke}} فنڪشنن ۾ اهو نه هوندو آهي۔
بي ترتيب
[سنواريو]{{#invoke:math|random}}
{{#invoke:math|random|max_value}}
{{#invoke:math|random|min_value|max_value}}
mm._random()
mm._random(max_value)
mm._random(min_value, max_value)
هڪ بي ترتيب (random) عدد پيدا ڪري ٿو۔
- جيڪڏهن ڪو دليل (argument) نه هجي ته پيدا ٿيندڙ عدد 0 کان وڏو يا برابر ۽ 1 کان ننڍو هوندو۔
- جيڪڏهن هڪ دليل ڏنو وڃي ته پيدا ٿيندڙ عدد 1 کان ان دليل تائين صحيح عدد هوندو۔ دليل مثبت صحيح عدد هجڻ گهرجي۔
- جيڪڏهن ٻه دليل ڏنا وڃن ته پيدا ٿيندڙ عدد انهن ٻن عددن جي وچ ۾ صحيح عدد هوندو۔ ٻنهي دليلن کي صحيح عدد هجڻ گهرجي، پر اهي منفي به ٿي سگهن ٿا۔
هي فنڪشن -232 کان گهٽ يا 232-1 کان وڏن عددن لاءِ صحيح نموني ڪم نٿو ڪري۔ اهڙن حالتن ۾ Module:Random استعمال ڪرڻ صلاح ڏني وڃي ٿي۔
ترتيب
[سنواريو]{{#invoke:math|order|n}}
mm._order(n)
ڪنهن عدد جي order of magnitude کي طئي ڪري ٿو۔
درستگي
[سنواريو]{{#invoke:math|precision|n}}
{{#invoke:math|precision|x=n}}
mm._precision(number_string)
ڪنهن عدد جي precision طئي ڪري ٿو۔ مثال طور:
- "4" لاءِ نتيجو "0"
- "4.567" لاءِ نتيجو "3"
- "100" لاءِ نتيجو "-2"
هي فنڪشن عدد جي string صورت کي پڙهي ٿو ۽ اهو به ڏسي ٿو ته ڇا عدد E notation ۾ آهي يا نه۔ تمام وڏن يا تمام وڌيڪ درست عددن کي Lua ۾ string طور داخل ڪرڻ بهتر آهي۔
وڏو عدد
[سنواريو]{{#invoke:math|max|v1|v2|v3|...}}
mm._max(v1, v2, v3, ...)
ڏنل عددن مان سڀ کان وڏو عدد واپس ڪري ٿو۔ جيڪي قدر عدد ۾ تبديل نه ٿي سگهن، انهن کي نظرانداز ڪيو ويندو آهي۔
وچولو عدد
[سنواريو]{{#invoke:math|median|v1|v2|v3|...}}
mm._median(v1, v2, v3, ...)
ڏنل قدرن مان median واپس ڪري ٿو۔
ننڍو عدد
[سنواريو]{{#invoke:math|min|v1|v2|v3|...}}
mm._min(v1, v2, v3, ...)
ڏنل قدرن مان سڀ کان ننڍو عدد واپس ڪري ٿو۔
حساب
[سنواريو]{{#invoke:math|sum|v1|v2|v3|...}}
mm._sum(v1, v2, v3, ...)
ڏنل عددن جو مجموعو (sum) واپس ڪري ٿو۔
سراسري
[سنواريو]{{#invoke:math|average|v1|v2|v3|...}}
mm._average(v1, v2, v3, ...)
ڏنل عددن جو اوسط (average) واپس ڪري ٿو۔ (وڌيڪ صحيح لفظن ۾، هي arithmetic mean آهي۔)
سڌو انگ
[سنواريو]{{#invoke:math|round|value|precision}}
{{#invoke:math|round|value=value|precision=precision}}
mm._round(value, precision)
ڪنهن عدد کي مخصوص precision تائين round ڪري ٿو۔ ڊفالٽ طور precision = 0 هوندي آهي، يعني ويجهي صحيح عدد تائين۔
فارمولو:
10 لاگ
[سنواريو]{{#invoke:math | log10 | x}}
mm._log10(x)
عدد x جو بنياد 10 وارو logarithm واپس ڪري ٿو۔
موڊ
[سنواريو]{{#invoke:math|mod|x|y}}
mm._mod(x, y)
عدد x کي y سان ورهائڻ بعد بچيل باقي (remainder) واپس ڪري ٿو۔
جي سي ڊي
[سنواريو]{{#invoke:math|gcd|v1|v2|...}}
mm._gcd(v1, v2, ...)
ڏنل عددن جو greatest common divisor (GCD) ڳولي ٿو۔
درست_نمونو
[سنواريو]{{#invoke:math|precision_format|value_string|precision}}
mm._precision_format(value_string, precision)
عدد کي مخصوص precision تائين round ڪري string طور فارميٽ ڪري ٿو۔
ونڊ
[سنواريو]{{#invoke:Math|divide|x|y|round=|precision=}}
mm._divide(x, y, round, precision)
x کي y سان ورهائي ٿو۔
- جيڪڏهن y عدد نه هجي ته y واپس ڪيو ويندو۔
- جيڪڏهن x عدد نه هجي ته x واپس ڪيو ويندو۔
- جيڪڏهن round صحيح هجي ته نتيجي ۾ decimal نه هوندي۔
- precision نتيجي جي درستگي طئي ڪري ٿي۔
صاف انگ
[سنواريو]local number, number_string = mm._cleanNumber(number_string)
هي مددگار فنڪشن آهي جيڪو ٻين Lua ماڊيولن مان سڏي سگهجي ٿو، پر {{#invoke}} مان نه۔
هي string يا عدد کي وٺي ان کي عدد ۾ تبديل ڪرڻ جي ڪوشش ڪندو آهي۔
جيڪڏهن ڪامياب ٿيو ته عدد ۽ ان جي string صورت واپس ڪندو، ٻي صورت ۾ nil, nil موٽائيندو۔
پڻ ڏسو
[سنواريو]
--[[
This module provides a number of basic mathematical operations.
]]
local yesno, getArgs -- lazily initialized
local p = {} -- Holds functions to be returned from #invoke, and functions to make available to other Lua modules.
local wrap = {} -- Holds wrapper functions that process arguments from #invoke. These act as intemediary between functions meant for #invoke and functions meant for Lua.
--[[
Helper functions used to avoid redundant code.
]]
local function err(msg)
-- Generates wikitext error messages.
return mw.ustring.format('<strong class="error">Formatting error: %s</strong>', msg)
end
local function unpackNumberArgs(args)
-- Returns an unpacked list of arguments specified with numerical keys.
local ret = {}
for k, v in pairs(args) do
if type(k) == 'number' then
table.insert(ret, v)
end
end
return unpack(ret)
end
local function makeArgArray(...)
-- Makes an array of arguments from a list of arguments that might include nils.
local args = {...} -- Table of arguments. It might contain nils or non-number values, so we can't use ipairs.
local nums = {} -- Stores the numbers of valid numerical arguments.
local ret = {}
for k, v in pairs(args) do
v = p._cleanNumber(v)
if v then
nums[#nums + 1] = k
args[k] = v
end
end
table.sort(nums)
for i, num in ipairs(nums) do
ret[#ret + 1] = args[num]
end
return ret
end
local function fold(func, ...)
-- Use a function on all supplied arguments, and return the result. The function must accept two numbers as parameters,
-- and must return a number as an output. This number is then supplied as input to the next function call.
local vals = makeArgArray(...)
local count = #vals -- The number of valid arguments
if count == 0 then return
-- Exit if we have no valid args, otherwise removing the first arg would cause an error.
nil, 0
end
local ret = table.remove(vals, 1)
for _, val in ipairs(vals) do
ret = func(ret, val)
end
return ret, count
end
--[[
Fold arguments by selectively choosing values (func should return when to choose the current "dominant" value).
]]
local function binary_fold(func, ...)
local value = fold((function(a, b) if func(a, b) then return a else return b end end), ...)
return value
end
--[[
random
Generate a random number
Usage:
{{#invoke: Math | random }}
{{#invoke: Math | random | maximum value }}
{{#invoke: Math | random | minimum value | maximum value }}
]]
function wrap.random(args)
local first = p._cleanNumber(args[1])
local second = p._cleanNumber(args[2])
return p._random(first, second)
end
function p._random(first, second)
math.randomseed(mw.site.stats.edits + mw.site.stats.pages + os.time() + math.floor(os.clock() * 1000000000))
-- math.random will throw an error if given an explicit nil parameter, so we need to use if statements to check the params.
if first and second then
if first <= second then -- math.random doesn't allow the first number to be greater than the second.
return math.random(first, second)
end
elseif first then
return math.random(first)
else
return math.random()
end
end
--[[
order
Determine order of magnitude of a number
Usage:
{{#invoke: Math | order | value }}
]]
function wrap.order(args)
local input_string = (args[1] or args.x or '0');
local input_number = p._cleanNumber(input_string);
if input_number == nil then
return err('order of magnitude input appears non-numeric')
else
return p._order(input_number)
end
end
function p._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 wrap.precision(args)
local input_string = (args[1] or args.x or '0');
local trap_fraction = args.check_fraction;
local input_number;
if not yesno then
yesno = require('Module:Yesno')
end
if yesno(trap_fraction, true) then -- Returns true for all input except nil, false, "no", "n", "0" and a few others. See [[Module:Yesno]].
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 = p._cleanNumber(input_string);
if input_string == nil then
return err('precision input appears non-numeric')
else
return p._precision(input_string)
end
end
function p._precision(x)
if type(x) == 'number' then
x = tostring(x)
end
x = string.upper(x)
local decimal = x:find('%.')
local exponent_pos = x:find('E')
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 | ... }}
Note, any values that do not evaluate to numbers are ignored.
]]
function wrap.max(args)
return p._max(unpackNumberArgs(args))
end
function p._max(...)
local max_value = binary_fold((function(a, b) return a > b end), ...)
if max_value then
return max_value
end
end
--[[
median
Find the median of set of numbers
Usage:
{{#invoke:Math | median | number1 | number2 | ...}}
OR
{{#invoke:Math | median }}
]]
function wrap.median(args)
return p._median(unpackNumberArgs(args))
end
function p._median(...)
local vals = makeArgArray(...)
local count = #vals
table.sort(vals)
if count == 0 then
return 0
end
if p._mod(count, 2) == 0 then
return (vals[count/2] + vals[count/2+1])/2
else
return vals[math.ceil(count/2)]
end
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 wrap.min(args)
return p._min(unpackNumberArgs(args))
end
function p._min(...)
local min_value = binary_fold((function(a, b) return a < b end), ...)
if min_value then
return min_value
end
end
--[[
sum
Finds the sum
Usage:
{{#invoke:Math| sum | value1 | value2 | ... }}
OR
{{#invoke:Math| sum }}
Note, any values that do not evaluate to numbers are ignored.
]]
function wrap.sum(args)
return p._sum(unpackNumberArgs(args))
end
function p._sum(...)
local sums, count = fold((function(a, b) return a + b end), ...)
if not sums then
return 0
else
return sums
end
end
--[[
average
Finds the average
Usage:
{{#invoke:Math| average | value1 | value2 | ... }}
OR
{{#invoke:Math| average }}
Note, any values that do not evaluate to numbers are ignored.
]]
function wrap.average(args)
return p._average(unpackNumberArgs(args))
end
function p._average(...)
local sum, count = fold((function(a, b) return a + b end), ...)
if not sum then
return 0
else
return sum / count
end
end
--[[
round
Rounds a number to specified precision
Usage:
{{#invoke:Math | round | value | precision }}
--]]
function wrap.round(args)
local value = p._cleanNumber(args[1] or args.value or 0)
local precision = p._cleanNumber(args[2] or args.precision or 0)
if value == nil or precision == nil then
return err('round input appears non-numeric')
else
return p._round(value, precision)
end
end
function p._round(value, precision)
local rescale = math.pow(10, precision or 0);
return math.floor(value * rescale + 0.5) / rescale;
end
--[[
log10
returns the log (base 10) of a number
Usage:
{{#invoke:Math | log10 | x }}
]]
function wrap.log10(args)
return math.log10(args[1])
end
--[[
mod
Implements the modulo operator
Usage:
{{#invoke:Math | mod | x | y }}
--]]
function wrap.mod(args)
local x = p._cleanNumber(args[1])
local y = p._cleanNumber(args[2])
if not x then
return err('first argument to mod appears non-numeric')
elseif not y then
return err('second argument to mod appears non-numeric')
else
return p._mod(x, y)
end
end
function p._mod(x, y)
local ret = x % y
if not (0 <= ret and ret < y) then
ret = 0
end
return ret
end
--[[
gcd
Calculates the greatest common divisor of multiple numbers
Usage:
{{#invoke:Math | gcd | value 1 | value 2 | value 3 | ... }}
--]]
function wrap.gcd(args)
return p._gcd(unpackNumberArgs(args))
end
function p._gcd(...)
local function findGcd(a, b)
local r = b
local oldr = a
while r ~= 0 do
local quotient = math.floor(oldr / r)
oldr, r = r, oldr - quotient * r
end
if oldr < 0 then
oldr = oldr * -1
end
return oldr
end
local result, count = fold(findGcd, ...)
return result
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 wrap.precision_format(args)
local value_string = args[1] or 0
local precision = args[2] or 0
return p._precision_format(value_string, precision)
end
function p._precision_format(value_string, precision)
-- For access to Mediawiki built-in formatter.
local lang = mw.getContentLanguage();
local value
value, value_string = p._cleanNumber(value_string)
precision = p._cleanNumber(precision)
-- Check for non-numeric input
if value == nil or precision == nil then
return err('invalid input when rounding')
end
local current_precision = p._precision(value)
local order = p._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
if order + p._precision(value_string) >= 14 then
precision = 13 - order;
end
end
-- If rounding off, truncate extra digits
if precision < current_precision then
value = p._round(value, precision)
current_precision = p._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
--[[
divide
Implements the division operator
Usage:
{{#invoke:Math | divide | x | y | round= | precision= }}
--]]
function wrap.divide(args)
local x = args[1]
local y = args[2]
local round = args.round
local precision = args.precision
if not yesno then
yesno = require('Module:Yesno')
end
return p._divide(x, y, yesno(round), precision)
end
function p._divide(x, y, round, precision)
if y == nil or y == "" then
return err("Empty divisor")
elseif not tonumber(y) then
if type(y) == 'string' and string.sub(y, 1, 1) == '<' then
return y
else
return err("Not a number: " .. y)
end
elseif x == nil or x == "" then
return err("Empty dividend")
elseif not tonumber(x) then
if type(x) == 'string' and string.sub(x, 1, 1) == '<' then
return x
else
return err("Not a number: " .. x)
end
else
local z = x / y
if round then
return p._round(z, 0)
elseif precision then
return p._round(z, precision)
else
return z
end
end
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 p._cleanNumber(number_string, unformat)
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, try unformatting the number_string
if unformat and number == nil then
-- Cannot use mw.language.getContentLanguage():parseFormattedNumber()
-- because, unlike {{formatnum:|R}}, it won't ignore operators (it
-- would return an error on "1,234+1,234" instead of "1234+1234")
number_string = mw.getCurrentFrame():callParserFunction("formatnum", {number_string, "R"})
number = tonumber(number_string)
end
-- 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
--[[
Wrapper function that does basic argument processing. This ensures that all functions from #invoke can use either the current
frame or the parent frame, and it also trims whitespace for all arguments and removes blank arguments.
]]
local mt = { __index = function(t, k)
return function(frame)
if not getArgs then
getArgs = require('Module:Arguments').getArgs
end
return wrap[k](getArgs(frame)) -- Argument processing is left to Module:Arguments. Whitespace is trimmed and blank arguments are removed.
end
end }
return setmetatable(p, mt)