Difference between revisions of "Module:BaseConvert"

From blackwiki
Jump to navigation Jump to search
blackwiki>Toohool
(←Created page with '-- -- Converts numbers to a specified base between 2 and 36, for use in -- templates such as {{binary}}, {{octal}}, {{hexadecimal}}, etc. -- local p = {} funct...')
 
blackwiki>Toohool
(add support for fractional parts with specified precision)
Line 2: Line 2:
 
-- Converts numbers to a specified base between 2 and 36, for use in
 
-- Converts numbers to a specified base between 2 and 36, for use in
 
-- templates such as {{binary}}, {{octal}}, {{hexadecimal}}, etc.
 
-- templates such as {{binary}}, {{octal}}, {{hexadecimal}}, etc.
 +
--
 +
-- If a number is passed in the precision argument, that number of digits
 +
-- will be shown following the radix point. If no precision is specified,
 +
-- however many digits are needed will be shown, up to 10.
 
--
 
--
  
 
local p = {}
 
local p = {}
  
−
function p._convert(n, base)
+
function p._convert(n, base, precision)
 +
    n = tonumber(n)
 +
   
 
     local digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
 
     local digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  
−
    n = math.floor(n)
 
 
     local sign = ''
 
     local sign = ''
 
     if n < 0 then
 
     if n < 0 then
Line 16: Line 21:
 
     end
 
     end
 
      
 
      
 +
    local i, f = math.modf(n)
 +
 
     local t = {}
 
     local t = {}
 
     repeat
 
     repeat
−
         local d = (n % base) + 1
+
         local d = (i % base) + 1
−
         n = math.floor(n / base)
+
         i = math.floor(i / base)
 
         table.insert(t, 1, digits:sub(d, d))
 
         table.insert(t, 1, digits:sub(d, d))
−
     until n == 0
+
     until i == 0
 +
    local intPart = table.concat(t, '')
 +
   
 +
    -- compute the fractional part
 +
    local tf = {}
 +
    while f > 0 and #tf < (precision or 10) do
 +
        f = f * base
 +
        i, f = math.modf(f)
 +
        table.insert(tf, digits:sub(i + 1, i + 1))
 +
    end
 +
   
 +
    -- add trailing zeros if needed
 +
    if precision and #tf < precision then
 +
        for i = 1, precision - #tf do
 +
            table.insert(tf, '0')
 +
        end
 +
    end
 +
 
 +
    fracPart = table.concat(tf, '')
 +
   
 +
    -- remove trailing zeros if not needed
 +
    if not precision then
 +
        fracPart = fracPart:gsub('0*$', '')
 +
    end
 +
   
 +
    -- add the radix point if needed
 +
    if #fracPart > 0 then
 +
        fracPart = '.' .. fracPart
 +
    end
 
      
 
      
−
     return sign .. table.concat(t, '')
+
     return sign .. intPart .. fracPart
 
end
 
end
  
Line 29: Line 64:
 
     local n = frame.args.n
 
     local n = frame.args.n
 
     local base = frame.args.base
 
     local base = frame.args.base
−
     return p._convert(n, base)
+
    local precision = frame.args.precision
 +
     return p._convert(n, base, precision)
 
end
 
end
  
 
return p
 
return p

Revision as of 02:43, 23 February 2013

Converts numbers to a specified base between 2 and 36, for use in templates such as {{binary}}, {{octal}}, {{hexadecimal}}, etc.

Example usage:

local BaseConvert = require('Module:BaseConvert')
BaseConvert.convert({n = 14600926, base = 16}) -- returns 'DECADE'

Arguments:

  • n - (required) the number to be converted, as a string. It may be a number instead, if the input base is 10.
  • base - (required) the base to which the number should be converted. May be between 2 and 36, inclusive.
  • from - the base of the input. Defaults to 10 (or 16 if the input has a leading '0x'). Note that bases other than 10 are not supported if the input has a fractional part.
  • precision - number of digits to be rendered after the radix point. Trailing zeros will be added if needed. If not specified, however many digits are needed will be shown, up to 10.
  • width - minimum number of digits to be rendered before the radix point. Leading zeros will be added if needed.
  • default - Value to return if n is empty or non-numeric. Defaults to the value of n.
  • prefix / suffix - wikitext to add before/after the returned result. Will not be added if n is empty or non-numeric. For example, you might use a prefix of 0x when converting to hex, or a suffix of <sub>8</sub> when converting to octal.

--
-- Converts numbers to a specified base between 2 and 36, for use in
-- templates such as {{binary}}, {{octal}}, {{hexadecimal}}, etc.
--
-- If a number is passed in the precision argument, that number of digits
-- will be shown following the radix point. If no precision is specified,
-- however many digits are needed will be shown, up to 10.
--

local p = {}

function p._convert(n, base, precision)
    n = tonumber(n)
    
    local digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'

    local sign = ''
    if n < 0 then
        sign = '-'
        n = -n
    end
    
    local i, f = math.modf(n)

    local t = {}
    repeat
        local d = (i % base) + 1
        i = math.floor(i / base)
        table.insert(t, 1, digits:sub(d, d))
    until i == 0
    local intPart = table.concat(t, '')
    
    -- compute the fractional part
    local tf = {}
    while f > 0 and #tf < (precision or 10) do
        f = f * base
        i, f = math.modf(f)
        table.insert(tf, digits:sub(i + 1, i + 1))
    end
    
    -- add trailing zeros if needed
    if precision and #tf < precision then
        for i = 1, precision - #tf do
            table.insert(tf, '0') 
        end
    end

    fracPart = table.concat(tf, '')
    
    -- remove trailing zeros if not needed
    if not precision then
        fracPart = fracPart:gsub('0*$', '')
    end
    
    -- add the radix point if needed
    if #fracPart > 0 then
        fracPart = '.' .. fracPart
    end
    
    return sign .. intPart .. fracPart
end

function p.convert(frame)
    local n = frame.args.n
    local base = frame.args.base
    local precision = frame.args.precision
    return p._convert(n, base, precision)
end

return p