Module:Math: Difference between revisions

adds expression checking, more error messages, and better handling of some precision format cases, and precision flooding check
en>Dragons flight
m (fmt)
en>Dragons flight
(adds expression checking, more error messages, and better handling of some precision format cases, and precision flooding check)
Line 1:
local z = {}
require( "mw.language" );
 
-- Clean numeric value
function z._cleanNumber( frame, number_string )
-- Attempt basic conversion
local number = tonumber( number_string )
-- If failed, attempt to evaluate input as an expression
if number == nil then
local attempt = frame:preprocess( '{{#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.
x number_string = xnumber_string:match( "^%s*(.-)%s*$" );
end
return number, number_string;
end
 
-- Generate random number
Line 17 ⟶ 42:
-- Determine order of magnitude
function z.order(frame)
returnlocal input_string = z._order(tonumber(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">Formatting error: Order of magnitude input appears non-numeric</strong>'
else
return z._order( input_number )
end
end
function z._order(x)
Line 26 ⟶ 59:
-- Determines precision of a number using the string representation
function z.precision( frame )
returnlocal input_string = z._precision( frame.args[1] or frame.args.x or '0' );
local input_number;
input_number, input_string = z._cleanNumber( frame, input_string );
if input_string == nil then
return '<strong class="error">Formatting error: Precision input appears non-numeric</strong>'
else
return z._precision( input_string )
end
end
function z._precision( x )
x = string.upper( x )
 
-- Remove leading / trailing whitespace
x = x:match "^%s*(.-)%s*$";
 
local decimal = string.find( x, '.', 1, true )
Line 66 ⟶ 104:
return ''
end
local max_value = tonumber( frame.args[1] )nil;
local i = 21;
while frame.args[i] ~= nil do
local val = tonumberz._cleanNumber( frame, frame.args[i] );
if val ~= nil then
if max_value == nil or val > max_value then
max_value = val;
end
Line 87 ⟶ 125:
return ''
end
local min_value = tonumber( frame.args[1] )nil;
local i = 21;
while frame.args[i] ~= nil do
local val = tonumberz._cleanNumber( frame, frame.args[i] );
if val ~= nil then
if min_value == nil or val < min_value then
min_value = val;
end
Line 105 ⟶ 143:
-- Rounds a number to specified precision
function z.round(frame)
local value, = tonumber(frame.args[1] or frame.args.value or 0)precision;
local precision = tonumber(frame.args[2] or frame.args.precision or 0);
value = z._cleanNumber( frame, frame.args[1] or frame.args.value or 0 );
return z._round( value, precision );
local precision = tonumberz._cleanNumber( frame, frame.args[2] or frame.args.precision or 0 );
if value == nil or precision == nil then
return '<strong class="error">Formatting error: Round input appears non-numeric</strong>'
else
return z._round( value, precision );
end
end
function z._round( value, precision )
Line 120 ⟶ 165:
local lang = mw.getContentLanguage();
local value_string, value, = tonumber( frame.args[1] or 0 )precision;
localvalue, precisionvalue_string = tonumberz._cleanNumber( frame, frame.args[21] or 0 );
precision = z._cleanNumber( frame, frame.args[2] or 0 );
-- Check for non-numeric input
Line 135 ⟶ 181:
-- some circumstances because the terminal digits will be inaccurately reported.
if order + precision >= 14 then
precisionorig_precision = 13z._precision( -value_string order);
if order + orig_precision >= 14 then
precision = 13 - order;
end
end
 
Line 165 ⟶ 214:
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);
 
formatted_num = formatted_num .. string.rep( '0', precision );
padding = precision;
if padding > 20 then
padding = 20;
end
formatted_num = formatted_num .. string.rep( '0', precisionpadding );
end
else
formatted_numpadding = formatted_num .. string.rep( '0', precision - current_precision );
if padding > 20 then
padding = 20;
end
formatted_num = formatted_num .. string.rep( '0', padding );
end
end
Anonymous user