Module:Math: Difference between revisions
m 1 revision imported: Content from Template:Location map+ on Wikipedia |
Rewrite rounding and precision code to run faster, other code cleanup including removing unused variables. Please revert if this causes any unexpected side effects |
||
| Line 140: | Line 140: | ||
local input_string = (args[1] or args.x or '0'); | local input_string = (args[1] or args.x or '0'); | ||
local trap_fraction = args.check_fraction; | local trap_fraction = args.check_fraction; | ||
if not yesno then | if not yesno then | ||
| Line 158: | Line 157: | ||
end | end | ||
local _, clean_string = p._cleanNumber(input_string); | |||
if | if clean_string == nil then | ||
return err('precision input appears non-numeric') | return err('precision input appears non-numeric') | ||
else | else | ||
return p._precision( | return p._precision(clean_string) | ||
end | end | ||
end | end | ||
| Line 170: | Line 169: | ||
x = tostring(x) | x = tostring(x) | ||
end | end | ||
local result = 0; | local result = 0; | ||
--subtract exponent | |||
local _, _, coefficient, exponent = x:find("^(.*)[eE](.*)$") | |||
if coefficient then | |||
result = result - tonumber(exponent) | result = result - (tonumber(exponent) or 0) | ||
x = coefficient | |||
end | end | ||
--add decimal places | |||
result = result + | local i, j = x:find('%..*$') | ||
if i then | |||
result = result + (j - i) | |||
return result | return result | ||
end | end | ||
--subtract trailing zeroes | |||
i, j = x:find('[^0]0+$') | |||
if i then | |||
result = result - | result = result - (j - i) | ||
end | end | ||
| Line 296: | Line 292: | ||
function p._sum(...) | function p._sum(...) | ||
local sums | local sums = fold((function(a, b) return a + b end), ...) | ||
if not sums then | if not sums then | ||
return 0 | return 0 | ||
| Line 424: | Line 420: | ||
return oldr | return oldr | ||
end | end | ||
local result | local result = fold(findGcd, ...) | ||
return result | return result | ||
end | end | ||
| Line 457: | Line 453: | ||
end | end | ||
local abs_value = math.abs(value) | |||
local current_precision = p._precision(value) | local current_precision = p._precision(value) | ||
local order = p._order(value) | local order = p._order(value) | ||
| Line 471: | Line 468: | ||
if precision < current_precision then | if precision < current_precision then | ||
value = p._round(value, precision) | value = p._round(value, precision) | ||
abs_value = math.abs(value) | |||
current_precision = p._precision(value) | current_precision = p._precision(value) | ||
end | end | ||
local formatted_num = lang:formatNum( | local formatted_num = lang:formatNum(abs_value) | ||
-- Handle cases requiring scientific notation | -- Handle cases requiring scientific notation | ||
if string.find(formatted_num, 'E', 1, true) | if math.abs(order) >= 9 or string.find(formatted_num, 'E', 1, true) then | ||
value = value * | value = value * (10 ^ (-order)) | ||
abs_value = math.abs(value) | |||
current_precision = current_precision + order | current_precision = current_precision + order | ||
precision = precision + order | precision = precision + order | ||
formatted_num = lang:formatNum( | formatted_num = lang:formatNum(abs_value) | ||
else | else | ||
order = 0; | order = 0; | ||
end | end | ||
formatted_num = | |||
-- Use proper unary minus sign rather than ASCII default | |||
formatted_num = ((value < 0) and '−' or '') .. formatted_num | |||
-- Pad with zeros, if needed | -- Pad with zeros, if needed | ||
| Line 589: | Line 582: | ||
]] | ]] | ||
function p._cleanNumber(number_string) | function p._cleanNumber(number_string, unformat) | ||
if type(number_string) == 'number' then | if type(number_string) == 'number' then | ||
-- We were passed a number, so we don't need to do any processing. | -- We were passed a number, so we don't need to do any processing. | ||
| Line 600: | Line 593: | ||
-- Attempt basic conversion | -- Attempt basic conversion | ||
local number = tonumber(number_string) | 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 failed, attempt to evaluate input as an expression | ||
| Line 628: | Line 630: | ||
]] | ]] | ||
local mt = { __index = function( | local mt = { __index = function(_, k) | ||
return function(frame) | return function(frame) | ||
if not getArgs then | if not getArgs then | ||