Module:Math: Difference between revisions
Jump to navigation
Jump to search
Content added Content deleted
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: | Line 1: | ||
local z = {} |
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. |
|||
⚫ | |||
end |
|||
return number, number_string; |
|||
end |
|||
-- Generate random number |
-- Generate random number |
||
Line 17: | Line 42: | ||
-- Determine order of magnitude |
-- Determine order of magnitude |
||
function z.order(frame) |
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">Formatting error: Order of magnitude input appears non-numeric</strong>' |
|||
else |
|||
return z._order( input_number ) |
|||
end |
|||
end |
end |
||
function z._order(x) |
function z._order(x) |
||
Line 26: | Line 59: | ||
-- Determines precision of a number using the string representation |
-- Determines precision of a number using the string representation |
||
function z.precision( frame ) |
function z.precision( frame ) |
||
local input_string = (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 |
end |
||
function z._precision( x ) |
function z._precision( x ) |
||
x = string.upper( x ) |
x = string.upper( x ) |
||
-- Remove leading / trailing whitespace |
|||
⚫ | |||
local decimal = string.find( x, '.', 1, true ) |
local decimal = string.find( x, '.', 1, true ) |
||
Line 66: | Line 104: | ||
return '' |
return '' |
||
end |
end |
||
local max_value = |
local max_value = nil; |
||
local i = |
local i = 1; |
||
while frame.args[i] ~= nil do |
while frame.args[i] ~= nil do |
||
local val = |
local val = z._cleanNumber( frame, frame.args[i] ); |
||
if val ~= nil then |
if val ~= nil then |
||
if val > max_value then |
if max_value == nil or val > max_value then |
||
max_value = val; |
max_value = val; |
||
end |
end |
||
Line 87: | Line 125: | ||
return '' |
return '' |
||
end |
end |
||
local min_value = |
local min_value = nil; |
||
local i = |
local i = 1; |
||
while frame.args[i] ~= nil do |
while frame.args[i] ~= nil do |
||
local val = |
local val = z._cleanNumber( frame, frame.args[i] ); |
||
if val ~= nil then |
if val ~= nil then |
||
if val < min_value then |
if min_value == nil or val < min_value then |
||
min_value = val; |
min_value = val; |
||
end |
end |
||
Line 105: | Line 143: | ||
-- Rounds a number to specified precision |
-- Rounds a number to specified precision |
||
function z.round(frame) |
function z.round(frame) |
||
local value |
local value, precision; |
||
⚫ | |||
value = z._cleanNumber( frame, frame.args[1] or frame.args.value or 0 ); |
|||
⚫ | |||
⚫ | |||
if value == nil or precision == nil then |
|||
return '<strong class="error">Formatting error: Round input appears non-numeric</strong>' |
|||
else |
|||
⚫ | |||
end |
|||
end |
end |
||
function z._round( value, precision ) |
function z._round( value, precision ) |
||
Line 120: | Line 165: | ||
local lang = mw.getContentLanguage(); |
local lang = mw.getContentLanguage(); |
||
local value |
local value_string, value, precision; |
||
value, value_string = z._cleanNumber( frame, frame.args[1] or 0 ); |
|||
precision = z._cleanNumber( frame, frame.args[2] or 0 ); |
|||
-- Check for non-numeric input |
-- Check for non-numeric input |
||
Line 135: | Line 181: | ||
-- some circumstances because the terminal digits will be inaccurately reported. |
-- some circumstances because the terminal digits will be inaccurately reported. |
||
if order + precision >= 14 then |
if order + precision >= 14 then |
||
orig_precision = z._precision( value_string ); |
|||
if order + orig_precision >= 14 then |
|||
precision = 13 - order; |
|||
end |
|||
end |
end |
||
Line 165: | Line 214: | ||
formatted_num = sign .. formatted_num; |
formatted_num = sign .. formatted_num; |
||
-- Pad with zeros, if needed |
-- Pad with zeros, if needed |
||
if current_precision < precision then |
if current_precision < precision then |
||
local padding; |
|||
if current_precision <= 0 then |
if current_precision <= 0 then |
||
if precision > 0 then |
if precision > 0 then |
||
local zero_sep = lang:formatNum( 1.1 ); |
local zero_sep = lang:formatNum( 1.1 ); |
||
formatted_num = formatted_num .. zero_sep:sub(2,2); |
formatted_num = formatted_num .. zero_sep:sub(2,2); |
||
⚫ | |||
padding = precision; |
|||
if padding > 20 then |
|||
padding = 20; |
|||
end |
|||
⚫ | |||
end |
end |
||
else |
else |
||
padding = precision - current_precision |
|||
if padding > 20 then |
|||
padding = 20; |
|||
end |
|||
formatted_num = formatted_num .. string.rep( '0', padding ); |
|||
end |
end |
||
end |
end |