Modul:Sandlådan/Exklamation/Matematik

Från Wikipedia

Dokumentation [visa] [redigera] [historik] [rensa sidcachen]


Användning av andra Lua-moduler[redigera wikitext]

För att använda modulen från normala wikisidor, behövs ingen speciell förberedelse. Om du använder modulen från en annan Lua-modul, måste du först lägga in denna kod:

local mm = require('Module:Math')

(Variabeln mm står för Modul:Matematik, du kan välja något mer beskrivande om du vill.)

De flesta funktionerna i modulen har en version för Lua och en version för #invoke. Det är möjligt att använda #invoke-funktioner från andra moduler, men med hjälp av Luafunktionerna har du fördelen att inte behöva komma åt ett Lua-ramobjekt. Luafunktioner föregås av _ , medan #invoke-funktioner inte gör det.

slump[redigera wikitext]

{{#invoke:Sandlådan/Exklamation/Matematik|slump}}
{{#invoke:Sandlådan/Exklamation/Matematik|slump|max_value}}
{{#invoke:Sandlådan/Exklamation/Matematik|slump|min_value|max_value}}
mm._random()
mm._random(max_value)
mm._random(min_value, max_value)

Genererar ett slumptal.

  • Om inga argument anges, är utvärdet större än eller lika med 0 och mindre än 1.
  • Om ett argument ges, är utvärdet ett heltal mellan 1 och det argumentet. Argumentet måste vara ett positivt heltal.
  • Om två argument ges, är utvärdet ett heltal mellan det första och det andra argumentet. Båda argumenten måste vara heltal, men kan vara negativa.

Funktionen kommer inte att fungera korrekt för tal mindre än -2^32 och större än 2^32 - 1 (även om detta kan variera beroende på maskinvara). Om du behöver använda tal utanför detta intervall, använd Modul:Sandlådan/Exklamation/Slump.

ordning[redigera wikitext]

{{#invoke:Sandlådan/Exklamation/Matematik/Matematik|ordning|n}}
mm._order(n)

Bestämmer magnitudordningen för ett tal.

precision[redigera wikitext]

{{#invoke:Sandlådan/Exklamation/Matematik|precision|n}}
{{#invoke:Sandlådan/Exklamation/Matematik|precision|x=n}}
mm._precision(number_string)

Bestämmer precisionen hos ett tal. Till exempel för "4" den ger "0", för "4,567" den ger "3", och för "100" kommer den att returnera "-2".

Funktionen försöker tolka strängbeteckning för talet, och detekterar om talet använder E-notation. Därför – när den anropas från Lua – bör mycket stora eller mycket exakta tal vara direkt invärde som strängar för att få korrekta resultat. Om de är invärde som tal kommer Luatolken ändra dem till E-notation och denna funktion returnerar precisionen av E-notation snarare än för det ursprungliga talet. Detta är inte ett problem när talet anropas från #invoke, eftersom alla invärden från #invoke är i strängformat.

max[redigera wikitext]

{{#invoke:Sandlådan/Exklamation/Matematik|max|v1|v2|v3|...}}
mm._max(v1, v2, v3, ...)

Returnerar maximivärdet från de angivna värdena. Värden som inte kan konverteras till tal ignoreras.

min[redigera wikitext]

{{#invoke:Sandlådan/Exklamation/Matematik|min|v1|v2|v3|...}}
mm._min(v1, v2, v3, ...)

Returnerar minivärdet från de angivna värdena. Värden som inte kan konverteras till tal ignoreras.

medium[redigera wikitext]

{{#invoke:Sandlådan/Exklamation/Matematik|medium|v1|v2|v3|...}}
mm._average(v1, v2, v3, ...)

Returnerar mediumet (det vill säga medelvärdet, av tekniska skäl kan inte Å, Ä och Ö användas) av de värden som anges. (Mer exakt är det värde som returneras det aritmetiska medelvärdet.) Värden som inte kan konverteras till tal ignoreras.

avrunda[redigera wikitext]

{{#invoke:Sandlådan/Exklamation/Matematik|avrunda|värde|precision}}
{{#invoke:Sandlådan/Exklamation/Matematik|avrunda|value=värde|precision=precision}}
mm._avrunda(value, precision)

Avrundar ett tal till specificerad precision.

mod[redigera wikitext]

{{#invoke:Sandlådan/Exklamation/Matematik|round|x|y}}
mm._round(x, y)

Gets x modulo y, or the remainder after x has been divided by y. This is accurate for integers up to 2^53; for larger integers Lua's modulo operator may return an erroneous value. This function deals with this problem by returning 0 if the modulo given by Lua's modulo operator is less than 0 or greater than y.

sgd[redigera wikitext]

{{#invoke:Sandlådan/Exklamation/Matematik|gcd|v1|v2|...}}
mm._gcd(v1, v2, ...)

Hittar den största gemensamma delaren av de angivna värdena. Värden som inte kan konverteras till tal ignoreras.

precision_format[redigera wikitext]

{{#invoke:Sandlådan/Exklamation/Matematik|precision_format|value_string|precision}}
mm._precision_format(value_string, precision)

Avrundar ett tal till specificerad precision och format enligt regler som ursprungligen användes för {{Rnd}}. Utvärdet är en sträng.

rensaTal[redigera wikitext]

local number, number_string = mm._rensaTal(number_string)

En hjälpfunktion som kan anropas från andra Lua-moduler, men inte från #invoke. Den tar en sträng eller ett numeriskt värde som invärde, och om värdet kan konverteras till ett tal, returnerar funktionen talet och talsträngen. Om värdet inte kan konverteras till ett tal, returneras nil, nil.

--[[

Modulen tillhandahåller en rad grundläggande matematiska operationer.

]]

local yesno = require('Module:Sandlådan/Exklamation/Ja-nej')
local getArgs = require('Module:Sandlådan/Exklamation/Argument').getArgs

local p = {} -- Håller funktioner som skall returneras från #invoke och funktioner tillgängliga för andra Lua-moduler.
local wrap = {} -- Håller inkapslingsfunktioner som bearbetar argument från #invoke. Dessa fungerar som mellanhand mellan funktioner avsedda för #invoke och funktioner avsedda för Lua.

--[[
Hjälpfunktioner som används för att undvika redundant kod.
]]

local function fel(msg)
	-- Genererar wikitextfelmeddelanden.
	return mw.ustring.format('<strong class="error">Formateringsfel: %s</strong>', msg)
end

local function uppackaTalArgument(args)
	-- Returnerar en uppackad lista med argument som anges med de numeriska nycklarna.
	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 skaparArgumentMatris(...)
	-- Gör en matris av argument från en lista över argument som kan inkludera nils.
	local args = {...} -- Table of arguments. It might contain nils or non-number values, so we can't use ipairs.
	local nums = {} -- Lagrar antalet giltiga numeriska argument.
	local ret = {}
	for k, v in pairs(args) do
		v = p._rensaTal(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 appliceraFunktionTillArgument(func, ...)
	-- Använder en funktion på alla tillhandahållna argument, och returnerar resultatet. Funktionen måste acceptera två tal som parametrar,
	-- och måste returnera ett tal som ett utvärde. Detta tal är sedan tillhandahållet som invärde till nästa funktions anrop.
	local vals = skaparArgumentMatris(...)	
	local count = #vals -- Antalet giltiga argument
	if count == 0 then return
		-- Avsluta om några giltiga argument har erhållits, avlägsna annars det första argumentet som skulle förorsakat ett fel.
		nil, 0
	end 
	local ret = table.remove(vals, 1)
	for _, val in ipairs(vals) do
		ret = func(ret, val)
	end
	return ret, count
end

--[[
slump

Genererar ett slumptal

Användning:
{{#invoke: Sandlådan/Exklamation/Matematik | slump }}
{{#invoke: Sandlådan/Exklamation/Matematik | slump | maximivärde }}
{{#invoke: Sandlådan/Exklamation/Matematik | slump | minimivärde | maximivärde }}
]]

function wrap.slump(args)
	local first = p._rensaTal(args[1])
	local second = p._rensaTal(args[2])
	return p._slump(first, second)
end

function p._slump(first, second)
	math.slumpseed(mw.site.stats.edits + mw.site.stats.pages + os.time() + math.floor(os.clock() * 1000000000))
	-- math.slump will throw an felor 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.slump doesn't allow the first number to be greater than the second.
			return math.slump(first, second)
		end
	elseif first then
		return math.slump(first)
	else
		return math.slump()
	end
end

--[[
ordning

Bestämmer magnitudordning av ett tal

Användning:
{{#invoke: Sandlådan/Exklamation/Matematik | ordning | värde }}
]]

function wrap.ordning(args)
	local input_string = (args[1] or args.x or '0');
	local input_number = p._rensaTal(input_string);
	if input_number == nil then
		return fel('ordning of magnitude input appears non-numeric')
	else
		return p._ordning(input_number)
	end    
end

function p._ordning(x)
	if x == 0 then return 0 end
	return math.floor(math.log10(math.abs(x)))
end

--[[
precision

Bestämmer precision av ett tal med hjälp av strängrepresentationen

Användning:
{{ #invoke: Sandlådan/Exklamation/Matematik | precision | värde }}
]]

function wrap.precision(args)
	local input_string = (args[1] or args.x or '0');
	local trap_fraction = args.check_fraction;
	local input_number;

	if yesno(trap_fraction, true) then -- Returns true for all input except nil, false, "no", "n", "0" and a few others. See [[Module:Sandlådan/Exklamation/Ja-nej]].
		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._rensaTal(input_string);
	if input_string == nil then
		return fel('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

Hittar maximumargumentet

Användning:
{{#invoke:Sandlådan/Exklamation/Matematik| max | värde1 | värde2 | ... }}

Notera, alla värden som inte utvärderas till tal ignoreras.
]]

function wrap.max(args)
	return p._max(uppackaTalArgument(args))
end

function p._max(...)
	local function maxOfTwo(a, b)
		if a > b then
			return a
		else
			return b
		end
	end
	local max_value = appliceraFunktionTillArgument(maxOfTwo, ...)
	if max_value then
		return max_value
	end
end

--[[
min 

Hittar minimumargumentet

Användning:
{{#invoke:Sandlådan/Exklamation/Matematik| min | värde1 | värde2 | ... }}
ELLER
{{#invoke:Sandlådan/Exklamation/Matematik| min }}

When used with no arguments, it takes its input from the parent
frame. Notera, alla värden som inte utvärderas till tal ignoreras.
]]

function wrap.min(args)
	return p._min(uppackaTalArgument(args))
end

function p._min(...)
	local function minOfTwo(a, b)
		if a < b then
			return a
		else
			return b
		end
	end
	local min_value = appliceraFunktionTillArgument(minOfTwo, ...)
	if min_value then
		return min_value
	end
end

--[[
medium 

Hittar mediumet (medelvärdet – av tekniska skäl kan Å, Ä och Ö inte användas i funktionsnamn)

Användning:
{{#invoke:Sandlådan/Exklamation/Matematik| medium | value1 | value2 | ... }}
ELLER
{{#invoke:Sandlådan/Exklamation/Matematik| medium }}

Notera, alla värden som inte utvärderas till tal ignoreras.
]]

function wrap.medium(args)
	return p._medium(uppackaTalArgument(args))
end

function p._medium(...)
	local function getSum(a, b)
		return a + b
	end
	local sum, count = appliceraFunktionTillArgument(getSum, ...)
	if not sum then
		return 0
	else
		return sum / count
	end
end

--[[
avrunda

Avrundar ett tal till specificerad precision

Användning:
{{#invoke:Sandlådan/Exklamation/Matematik | avrunda | värde | precision }}

--]]

function wrap.avrunda(args)
	local value = p._rensaTal(args[1] or args.value or 0)
	local precision = p._rensaTal(args[2] or args.precision or 0)
	if value == nil or precision == nil then
		return fel('avrunda input appears non-numeric')
	else
		return p._avrunda(value, precision)
	end    
end

function p._avrunda(value, precision)
	local rescale = math.pow(10, precision or 0);
	return math.floor(value * rescale + 0.5) / rescale;
end

--[[
mod

Implementerar modulooperatorn

Användning:
{{#invoke:Sandlådan/Exklamation/Matematik | mod | x | y }}

--]]

function wrap.mod(args)
	local x = p._rensaTal(args[1])
	local y = p._rensaTal(args[2])
	if not x then
		return fel('Första argumentet att modifiera verkar vara icke-numeriskt')
	elseif not y then
		return fel('Andra argumentet att modifiera verkar vara icke-numeriskt')
	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

--[[
sgd

Beräknar SGD (största gemensamma delare) av multipla tal

Användning:
{{#invoke:Sandlådan/Exklamation/Matematik | sgd | värde 1 | värde 2 | värde 3 | ... }}
--]]

function wrap.sgd(args)
	return p._sgd(uppackaTalArgument(args))
end

function p._sgd(...)
	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 = appliceraFunktionTillArgument(findGcd, ...)
	return result
end

--[[
precision_format

Avrundar ett tal till specificerad precision och formaterar enligt regler.
Utvärdet är en sträng.

Användning:
{{#invoke: Sandlådan/Exklamation/Matematik | 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._rensaTal(value_string)
	precision = p._rensaTal(precision)

	-- Check for non-numeric input
	if value == nil or precision == nil then
		return fel('Ogiltigt invärde vid avrundning')
	end

	local current_precision = p._precision(value)
	local ordning = p._ordning(value)

	-- Due to avrunda-off effects it is neccesary to limit the returned precision under
	-- some circumstances because the terminal digits will be inaccurately reported.
	if ordning + precision >= 14 then
		orig_precision = p._precision(value_string)
		if ordning + orig_precision >= 14 then
			precision = 13 - ordning;        
		end        
	end

	-- If avrundaing off, truncate extra digits
	if precision < current_precision then
		value = p._avrunda(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(ordning) >= 9 then
		value = value * math.pow(10, -ordning)
		current_precision = current_precision + ordning
		precision = precision + ordning
		formatted_num = lang:formatNum(math.abs(value))
	else
		ordning = 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 ordning ~= 0 then
		-- Use proper unary minus sign rather than ASCII default
		if ordning < 0 then
			ordning = '−' .. lang:formatNum(math.abs(ordning))
		else
			ordning = lang:formatNum(ordning)
		end    

		formatted_num = formatted_num .. '<span style="margin:0 .15em 0 .25em">×</span>10<sup>' .. ordning .. '</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 p._rensaTal(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 frame = mw.getCurrentFrame()
		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
		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 function makeWrapper(funcName)
	return function (frame)
		local args = getArgs(frame) -- Argument processing is left to Module:Sandlådan/Exklamation/Argument. Whitespace is trimmed and blank arguments are removed.
		return wrap[funcName](args)
	end
end

for funcName in pairs(wrap) do
	p[funcName] = makeWrapper(funcName)
end

-- delare --
--[[
  delare, skriver ut alla delare till ett givet tal 
  parametrar
  ==========
  tal: talet vars delare söks
  separator (frivillig): den teckensträng som ska skrivas ut mellan delarna.
  Ett komma och ett mellanslag sätts om separatorn ej används 
  exempel
  =======
  {{#invoke:Modulnamn|delare|tal=58166717|separator=,}} 
  ger resultatet
  1,7,673,4711,12347,86429,8309531,58166717
]]
-- Skapad av Larske
function p.delare (frame)
   local args = frame.args
   tal = frame.args['tal'] or frame.args[1]
   tal=string.gsub(tal,'([^0-9])','')
   tal=tonumber(tal)
   tal=math.abs(tal)
   sep = frame.args['separator'] or frame.args[2] or ', '
   delare = {}
   for i = 1, math.sqrt(tal) do
      if tal % i == 0 then 
         table.insert(delare, i)
	 if i ~= math.sqrt(tal) then
	    table.insert(delare, tal/i)
	 end
      end 	
   end
   table.sort(delare)
   return table.concat(delare,sep)
end

-- sgd2 beräknar största gemensamma delare till två heltal, a och b
function p.sgd2(frame) 
  local a = frame.args.a+0
  local b = frame.args.b+0
  if a < b then
    t = a
    a = math.abs(b)
    b = math.abs(t)
  end      
  while b > 0 do
    c = a % b
    a = b
    b = c
  end
  return a
end

return p