Lompat ke isi

Modul:Math

Nibak Wikipedia

Dokumentasi untuk modul ini dapat dibuat diModul:Math/doc

--[[

This module provides a number of basic mathematical operations.

]]
localz={}

-- Generate random number
functionz.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])

iffirstthen-- if NaN or nil, will skip down to final return
iffirst<=secondthen-- could match if both nil, but already checked that first is a number in last line
returnmath.random(first,second)
end
returnmath.random(first)
end
returnmath.random()
end

--[[
order

Determine order of magnitude of a number

Usage:
{{#invoke: Math | order | value }}
]]
functionz.order(frame)
localinput_string=(frame.args[1]orframe.args.xor'0');
localinput_number;

input_number=z._cleanNumber(frame,input_string);
ifinput_number==nilthen
return'<strong class= "error" >Formatting error: Order of magnitude input appears non-numeric</strong>'
else
returnz._order(input_number)
end
end
functionz._order(x)
ifx==0thenreturn0end
returnmath.floor(math.log10(math.abs(x)))
end

--[[
precision

Detemines the precision of a number using the string representation

Usage:
{{ #invoke: Math | precision | value }}
]]
functionz.precision(frame)
localinput_string=(frame.args[1]orframe.args.xor'0');
localtrap_fraction=frame.args.check_fractionorfalse;
localinput_number;

iftype(trap_fraction)=='string'then
trap_fraction=trap_fraction:lower();
iftrap_fraction=='false'ortrap_fraction=='0'or
trap_fraction=='no'ortrap_fraction==''then
trap_fraction=false;
else
trap_fraction=true;
end
end

iftrap_fractionthen
localpos=string.find(input_string,'/',1,true);
ifpos~=nilthen
ifstring.find(input_string,'/',pos+1,true)==nilthen
localdenominator=string.sub(input_string,pos+1,-1);
localdenom_value=tonumber(denominator);
ifdenom_value~=nilthen
returnmath.log10(denom_value);
end
end
end
end

input_number,input_string=z._cleanNumber(frame,input_string);
ifinput_string==nilthen
return'<strong class= "error" >Formatting error: Precision input appears non-numeric</strong>'
else
returnz._precision(input_string)
end
end
functionz._precision(x)
x=string.upper(x)

localdecimal=string.find(x,'.',1,true)
localexponent_pos=string.find(x,'E',1,true)
localresult=0;

ifexponent_pos~=nilthen
localexponent=string.sub(x,exponent_pos+1)
x=string.sub(x,1,exponent_pos-1)
result=result-tonumber(exponent)
end

ifdecimal~=nilthen
result=result+string.len(x)-decimal
returnresult
end

localpos=string.len(x);
whilex:byte(pos)==string.byte('0')do
pos=pos-1
result=result-1
ifpos<=0then
return0
end
end

returnresult
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.
]]
functionz.max(frame)
localargs=frame.args;

ifargs[1]==nilthen
localparent=frame:getParent();
args=parent.args;
end
localmax_value=nil;

locali=1;
whileargs[i]~=nildo
localval=z._cleanNumber(frame,args[i]);
ifval~=nilthen
ifmax_value==nilorval>max_valuethen
max_value=val;
end
end
i=i+1;
end

returnmax_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.
]]
functionz.min(frame)
localargs=frame.args;

ifargs[1]==nilthen
localparent=frame:getParent();
args=parent.args;
end
localmin_value=nil;

locali=1;
whileargs[i]~=nildo
localval=z._cleanNumber(frame,args[i]);
ifval~=nilthen
ifmin_value==nilorval<min_valuethen
min_value=val;
end
end
i=i+1;
end

returnmin_value
end

--[[
average

Finds the average

Usage:
{{#invoke:Math| average | value1 | value2 |... }}
OR
{{#invoke:Math| average }}

When used with no arguments, it takes its input from the parent
frame. Note, any values that do not evaluate to numbers are ignored.
]]
functionz.average(frame)
localargs=frame.args;
ifargs[1]==nilthen
localparent=frame:getParent();
args=parent.args;
end
localsum=0;
localcount=0;

locali=1;
whileargs[i]~=nildo
localval=z._cleanNumber(frame,args[i]);
ifval~=nilthen
sum=sum+val
count=count+1
end
i=i+1;
end

return(count==0and0orsum/count)
end

--[[
round

Rounds a number to specified precision

Usage:
{{#invoke:Math | round | value | precision }}

--]]
functionz.round(frame)
localvalue,precision;

value=z._cleanNumber(frame,frame.args[1]orframe.args.valueor0);
precision=z._cleanNumber(frame,frame.args[2]orframe.args.precisionor0);

ifvalue==nilorprecision==nilthen
return'<strong class= "error" >Formatting error: Round input appears non-numeric</strong>'
else
returnz._round(value,precision);
end
end
functionz._round(value,precision)
localrescale=math.pow(10,precision);
returnmath.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 }}
]]
functionz.precision_format(frame)
-- For access to Mediawiki built-in formatter.
locallang=mw.getContentLanguage();

localvalue_string,value,precision;
value,value_string=z._cleanNumber(frame,frame.args[1]or0);
precision=z._cleanNumber(frame,frame.args[2]or0);

-- Check for non-numeric input
ifvalue==nilorprecision==nilthen
return'<strong class= "error" >Formatting error: invalid input when rounding</strong>'
end

localcurrent_precision=z._precision(value);

localorder=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.
iforder+precision>=14then
orig_precision=z._precision(value_string);
iforder+orig_precision>=14then
precision=13-order;
end
end

-- If rounding off, truncate extra digits
ifprecision<current_precisionthen
value=z._round(value,precision);
current_precision=z._precision(value);
end

localformatted_num=lang:formatNum(math.abs(value));
localsign;

-- Use proper unary minus sign rather than ASCII default
ifvalue<0then
sign='−';
else
sign='';
end

-- Handle cases requiring scientific notation
ifstring.find(formatted_num,'E',1,true)~=nilormath.abs(order)>=9then
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
ifcurrent_precision<precisionthen
localpadding;
ifcurrent_precision<=0then
ifprecision>0then
localzero_sep=lang:formatNum(1.1);
formatted_num=formatted_num..zero_sep:sub(2,2);

padding=precision;
ifpadding>20then
padding=20;
end

formatted_num=formatted_num..string.rep('0',padding);
end
else
padding=precision-current_precision
ifpadding>20then
padding=20;
end
formatted_num=formatted_num..string.rep('0',padding);
end
end

-- Add exponential notation, if necessary.
iforder~=0then
-- Use proper unary minus sign rather than ASCII default
iforder<0then
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

returnformatted_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.
]]

functionz._cleanNumber(frame,number_string)
ifnumber_string==nilornumber_string:len()==0then
returnnil,nil;
end

-- Attempt basic conversion
localnumber=tonumber(number_string)

-- If failed, attempt to evaluate input as an expression
ifnumber==nilthen
localattempt=frame:preprocess('{{#expr: '..number_string..'}}');
attempt=tonumber(attempt);
ifattempt~=nilthen
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=number_string:match("^%s*(.-)%s*$");
end

returnnumber,number_string;
end

returnz