Jump to content

Module:BaseConvert/sandbox: Difference between revisions

From Wikipedia, the free encyclopedia
Content deleted Content added
require('Module:Log globals') rm test
remove trailing whitespace
Line 4: Line 4:


local function normalizeFullWidthChars(s)
local function normalizeFullWidthChars(s)
return mw.ustring.gsub(s, '[!-~]', function(s)
return mw.ustring.gsub(s, '[!-~]', function(s)
return mw.ustring.char(mw.ustring.codepoint(s, 1) - 0xFEE0)
return mw.ustring.char(mw.ustring.codepoint(s, 1) - 0xFEE0)
end)
end)
end
end


local function _convert(n, base, from, precision, width, default, prefix, suffix)
local function _convert(n, base, from, precision, width, default, prefix, suffix)
n = '' .. n -- convert to a string
n = '' .. n -- convert to a string

-- strip off any leading '0x' (unless x is a valid digit in the input base)
-- strip off any leading '0x' (unless x is a valid digit in the input base)
from = tonumber(from)
from = tonumber(from)
Line 26: Line 26:
n, c = n:gsub('^-', '')
n, c = n:gsub('^-', '')
if c > 0 then sign = '-' end
if c > 0 then sign = '-' end

-- replace any full-width Unicode characters in the string with their ASCII equivalents
-- replace any full-width Unicode characters in the string with their ASCII equivalents
n = normalizeFullWidthChars(n)
n = normalizeFullWidthChars(n)

-- handle scientific notation with whitespace around the 'e' e.g. '5 e7'
-- handle scientific notation with whitespace around the 'e' e.g. '5 e7'
n = n:gsub('%s*[eE]%s*', 'e')
n = n:gsub('%s*[eE]%s*', 'e')

from = from or 10
from = from or 10
local num = tonumber(n, from)
local num = tonumber(n, from)
Line 38: Line 38:
precision = tonumber(precision)
precision = tonumber(precision)
width = tonumber(width)
width = tonumber(width)

if not num or not base then return default or n end
if not num or not base then return default or n end

local i, f = math.modf(num)
local i, f = math.modf(num)


Line 50: Line 50:
until i == 0
until i == 0
while #t < (width or 0) do
while #t < (width or 0) do
table.insert(t, 1, '0')
table.insert(t, 1, '0')
end
end
local intPart = table.concat(t, '')
local intPart = table.concat(t, '')

-- compute the fractional part
-- compute the fractional part
local tf = {}
local tf = {}
Line 61: Line 61:
table.insert(tf, digits:sub(i + 1, i + 1))
table.insert(tf, digits:sub(i + 1, i + 1))
end
end

-- add trailing zeros if needed
-- add trailing zeros if needed
if precision and #tf < precision then
if precision and #tf < precision then
for i = 1, precision - #tf do
for i = 1, precision - #tf do
table.insert(tf, '0')
table.insert(tf, '0')
end
end
end
end

local fracPart
local fracPart
fracPart = table.concat(tf, '')
fracPart = table.concat(tf, '')

-- remove trailing zeros if not needed
-- remove trailing zeros if not needed
if not precision then
if not precision then
fracPart = fracPart:gsub('0*$', '')
fracPart = fracPart:gsub('0*$', '')
end
end

-- add the radix point if needed
-- add the radix point if needed
if #fracPart > 0 then
if #fracPart > 0 then
fracPart = '.' .. fracPart
fracPart = '.' .. fracPart
end
end

return (prefix or '') .. sign .. intPart .. fracPart .. (suffix or '')
return (prefix or '') .. sign .. intPart .. fracPart .. (suffix or '')
end
end
Line 93: Line 93:
args = frame
args = frame
end
end

local n = args.n
local n = args.n
local base = args.base
local base = args.base

Revision as of 06:55, 12 April 2022

local p = {}

local digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'

local function normalizeFullWidthChars(s)
    return mw.ustring.gsub(s, '[!-~]', function(s)
        return mw.ustring.char(mw.ustring.codepoint(s, 1) - 0xFEE0)
    end)
end

local function _convert(n, base, from, precision, width, default, prefix, suffix)
    n = '' .. n   -- convert to a string

    -- strip off any leading '0x' (unless x is a valid digit in the input base)
    from = tonumber(from)
    if not from or from < 34 then
        local c
        n, c = n:gsub('^(-?)0[Xx]', '%1')
        if c > 0 and not from then from = 16 end
    end

    -- check for a negative sign. Do this while the input is still in string form,
    -- because tonumber doesn't support negative numbers in non-10 bases.
    local sign = ''
    local c
    n, c = n:gsub('^-', '')
    if c > 0 then sign = '-' end

    -- replace any full-width Unicode characters in the string with their ASCII equivalents
    n = normalizeFullWidthChars(n)

    -- handle scientific notation with whitespace around the 'e' e.g. '5 e7'
    n = n:gsub('%s*[eE]%s*', 'e')

    from = from or 10
    local num = tonumber(n, from)
    base = tonumber(base)
    precision = tonumber(precision)
    width = tonumber(width)

    if not num or not base then return default or n end

    local i, f = math.modf(num)

    local t = {}
    repeat
        local d = (i % base) + 1
        i = math.floor(i / base)
        table.insert(t, 1, digits:sub(d, d))
    until i == 0
    while #t < (width or 0) do
        table.insert(t, 1, '0')
    end
    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

	local fracPart
	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 (prefix or '') .. sign .. intPart .. fracPart .. (suffix or '')
end

function p.convert(frame)
    -- Allow for invocation via #invoke or directly from another module
    local args
    if frame == mw.getCurrentFrame() then
        args = frame.args
    else
        args = frame
    end

    local n = args.n
    local base = args.base
    local from = args.from
    local precision = args.precision
    local width = args.width
    local default = args.default
    local prefix = args.prefix
    local suffix = args.suffix
    return _convert(n, base, from, precision, width, default, prefix, suffix)
end

setmetatable(p, {
	__index = function(t, k)
		from, base = k:match('^([0-9]+)to([0-9]+)$')
		if not from then return nil end
		return function(frame)
			args = frame.args
    		return _convert(mw.text.trim(args[1]), base, from, args['precision'], args['width'],
    			args['default'], args['prefix'], args['suffix'])
    	end
	end
})

return p