<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>https://wiki.cloudmodding.com/mm/Module:Radix/history?feed=atom</id>
		<title>Module:Radix - Revision history</title>
		<link rel="self" type="application/atom+xml" href="https://wiki.cloudmodding.com/mm/Module:Radix/history?feed=atom"/>
		<link rel="alternate" type="text/html" href="https://wiki.cloudmodding.com/mm/Module:Radix/history"/>
		<updated>2026-04-13T05:43:08Z</updated>
		<subtitle>Revision history for this page on the wiki</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>https://wiki.cloudmodding.com/wmm/index.php?title=Module:Radix&amp;diff=642&amp;oldid=prev</id>
		<title>ShimmerFairy: Create lua functions for handling variously-radixed numbers, and an #invoke-able converter</title>
		<link rel="alternate" type="text/html" href="https://wiki.cloudmodding.com/wmm/index.php?title=Module:Radix&amp;diff=642&amp;oldid=prev"/>
				<updated>2016-04-07T06:14:48Z</updated>
		
		<summary type="html">&lt;p&gt;Create lua functions for handling variously-radixed numbers, and an #invoke-able converter&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;-- module providing various functions for handling numbers in radices 2..36&lt;br /&gt;
&lt;br /&gt;
-- note: not using tonumber() since it's not as featurful as we need&lt;br /&gt;
&lt;br /&gt;
local p = {};&lt;br /&gt;
&lt;br /&gt;
local LU = require('libraryUtil');&lt;br /&gt;
local B32 = require('bit32');&lt;br /&gt;
&lt;br /&gt;
-- this function parses an integer; it's global to allow use by other modules on&lt;br /&gt;
-- the site. This function will stop at the first non-numeric character&lt;br /&gt;
-- encountered.&lt;br /&gt;
function p.parse_int(numstr, radix)&lt;br /&gt;
	radix = radix or 0;&lt;br /&gt;
    -- some type-checking&lt;br /&gt;
    LU.checkType(&amp;quot;parse_int&amp;quot;, 1, numstr, &amp;quot;string&amp;quot;);&lt;br /&gt;
    LU.checkType(&amp;quot;parse_int&amp;quot;, 2, radix, &amp;quot;number&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    assert(radix == math.floor(radix), &amp;quot;radix must be an integer, yet isn't&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    if radix ~= 0 then&lt;br /&gt;
        assert(2 &amp;lt;= radix, &amp;quot;radix must be at least 2 (and at most 36)&amp;quot;);&lt;br /&gt;
        assert(radix &amp;lt;= 36, &amp;quot;radix must be at most 36 (and at least 2)&amp;quot;);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- now, the function&lt;br /&gt;
&lt;br /&gt;
    local signage = 1;&lt;br /&gt;
&lt;br /&gt;
    if mw.ustring.sub(numstr, 1, 1) == '-' then&lt;br /&gt;
        signage = -1;&lt;br /&gt;
        numstr = mw.ustring.sub(numstr, 2);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if radix == 0 then&lt;br /&gt;
        -- we'll need to figure out the radix on our own, then&lt;br /&gt;
        local ohprefix = mw.ustring.sub(numstr, 1, 2);&lt;br /&gt;
        if ohprefix == &amp;quot;0x&amp;quot; then&lt;br /&gt;
            radix = 16;&lt;br /&gt;
        elseif ohprefix == &amp;quot;0o&amp;quot; then&lt;br /&gt;
            radix = 8;&lt;br /&gt;
        elseif ohprefix == &amp;quot;0b&amp;quot; then&lt;br /&gt;
            radix = 2;&lt;br /&gt;
        elseif ohprefix == &amp;quot;0d&amp;quot; then&lt;br /&gt;
            radix = 10;&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        -- if we changed the radix, then we need to take the oh prefix out of&lt;br /&gt;
        -- the string, otherwise there's nothing to remove, and we default to&lt;br /&gt;
        -- base 10.&lt;br /&gt;
&lt;br /&gt;
        if radix ~= 0 then&lt;br /&gt;
            numstr = mw.ustring.sub(numstr, 3);&lt;br /&gt;
        else&lt;br /&gt;
            radix = 10;&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- and now we get to the conversion part&lt;br /&gt;
    local res = 0;&lt;br /&gt;
&lt;br /&gt;
    -- loop in terms of codepoints so we're already set to do it if/when we&lt;br /&gt;
    -- expand the range of characters handled in the future (the oh prefix stuff&lt;br /&gt;
    -- earlier can be safely done assuming ASCII)&lt;br /&gt;
    for cp in mw.ustring.gcodepoint(numstr) do&lt;br /&gt;
        local thedigit;&lt;br /&gt;
        if (0x30 &amp;lt;= cp) and (cp &amp;lt;= 0x39) then -- digits 0..9&lt;br /&gt;
            thedigit = B32.band(cp, 0x0F);&lt;br /&gt;
        elseif (0x41 &amp;lt;= B32.band(cp, 0xDF)) and (B32.band(cp, 0xDF) &amp;lt;= 0x5A) then -- ASCII letters A..Z, any case&lt;br /&gt;
            thedigit = B32.band(cp, 0xDF) - 0x41 + 10;&lt;br /&gt;
        else -- some unrecognizable character, we have to stop&lt;br /&gt;
            break;&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        if thedigit &amp;gt;= radix then&lt;br /&gt;
            -- while we could count this an invalid character and break, you&lt;br /&gt;
            -- likely made a mistake, so we'll error instead&lt;br /&gt;
            error(&amp;quot;Invalid digit for radix!&amp;quot;);&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        res = res * radix + thedigit;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return res * signage;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- XXX TODO a function to parse floats, when needed&lt;br /&gt;
&lt;br /&gt;
-- writes a number, int or float, to a string&lt;br /&gt;
function p.write_num(thenum, radix)&lt;br /&gt;
    -- type-checking&lt;br /&gt;
    LU.checkType(&amp;quot;write_num&amp;quot;, 1, thenum, &amp;quot;number&amp;quot;);&lt;br /&gt;
    LU.checkType(&amp;quot;write_num&amp;quot;, 2, radix, &amp;quot;number&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    assert(radix == math.floor(radix), &amp;quot;radix must be an integer, yet isn't&amp;quot;);&lt;br /&gt;
    assert(2 &amp;lt;= radix, &amp;quot;radix must be at least 2 (and at most 36)&amp;quot;);&lt;br /&gt;
    assert(radix &amp;lt;= 36, &amp;quot;radix must be at most 36 (and at least 2)&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    -- function&lt;br /&gt;
    local res = &amp;quot;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
    if thenum &amp;lt; 0 then&lt;br /&gt;
        res = res .. &amp;quot;-&amp;quot;;&lt;br /&gt;
        thenum = math.abs(thenum);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local ipart = math.floor(thenum);&lt;br /&gt;
    local fpart = thenum - ipart;&lt;br /&gt;
&lt;br /&gt;
    local charlist = &amp;quot;0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
    -- it's easier to handle the integer part if we turn it into a number less&lt;br /&gt;
    -- than one first (note that floor(log()) + 1 is just a neat trick to get&lt;br /&gt;
    -- the length of an integer number in the chosen radix)&lt;br /&gt;
    local isize = math.floor(math.log(ipart)/math.log(radix)) + 1;&lt;br /&gt;
    ipart = ipart / (radix ^ isize);&lt;br /&gt;
&lt;br /&gt;
    -- now to write out the integer part; we multiply the integer part by the&lt;br /&gt;
    -- radix, take the integer part of _that_, and subtract the written digit&lt;br /&gt;
    -- from ipart.&lt;br /&gt;
    for i = 1, isize do&lt;br /&gt;
        ipart = ipart * radix;&lt;br /&gt;
        res = res .. mw.ustring.sub(charlist, math.floor(ipart) + 1, math.floor(ipart) + 1);&lt;br /&gt;
        ipart = ipart - math.floor(ipart);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- if there's a fractional part, get to that now&lt;br /&gt;
    if fpart ~= 0 then&lt;br /&gt;
        res = res .. &amp;quot;.&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        -- note that this is just like how we handled the integer part, only we&lt;br /&gt;
        -- didn't have to divide first.&lt;br /&gt;
        while fpart ~= 0 do&lt;br /&gt;
            fpart = fpart * radix;&lt;br /&gt;
            res = res .. mw.ustring.sub(charlist, math.floor(fpart) + 1, math.floor(fpart) + 1);&lt;br /&gt;
            fpart = fpart - math.floor(fpart);&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return res;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- only this function can be #invoke'd, the ones above can't.&lt;br /&gt;
function p.ConvertInteger(frame)&lt;br /&gt;
    local the_num  = frame.args[1];&lt;br /&gt;
    local from_rad = tonumber(frame.args[2]) or 0;&lt;br /&gt;
    local to_rad = tonumber(frame.args[3]) or 10;&lt;br /&gt;
&lt;br /&gt;
    return p.write_num(p.parse_int(the_num, from_rad), to_rad);&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p;&lt;/div&gt;</summary>
		<author><name>ShimmerFairy</name></author>	</entry>

	</feed>