Module:Radix: Difference between revisions

From Nguhcraft Wiki
Jump to navigation Jump to search
Astaryuu (talk | contribs)
No edit summary
Astaryuu (talk | contribs)
rejigger this thing to work with negative b
Line 2: Line 2:


r.decimal_to = function(frame)
r.decimal_to = function(frame)
-- Get arguments from call
-- Get number (in base 10)
decimal = tonumber(frame.args[1])
-- If decimal is 0 or 1, return decimal
if decimal == 0 or decimal == 1 then
return tostring(decimal)
end
-- Do I use separators?
format_output = format_output and format_output or true
format_output = format_output and format_output or true
local decimal = math.abs(tonumber(frame.args[1]))
-- Get radix to convert to
local sign = decimal > 0 and "" or "-"
radix = tonumber(frame.args[2])
-- If decimal is 1, return itself
-- sign is equal to sign(decimal) if radix is positive, and 1 otherwise
if decimal == 1 then
sign = radix > 0 and decimal / math.abs(decimal) or 1
-- If radix is not an integer: Round to nearest integer for now
radix = radix < 0 and math.ceil(x) or math.floor(x)
-- If abs(radix) is 1, 0, or > 36, return decimal
if radix == 0 or math.abs(radix) == 1 or math.abs(radix) > 36 then  
return tostring(decimal)
return tostring(decimal)
end
end
-- Newradix is the radix to convert to
local newradix = tonumber(frame.args[2])
-- characters are based on other proglangs' parsing
local characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-- precision is the number of digits below 1 to use
-- precision is the number of digits below 1 to use
-- if decimal is less than 1/newradix ^ precision, return 0
-- if decimal is less than 1/newradix ^ precision, return 0
local precision = tonumber(frame.args[3]) or 0
precision = tonumber(frame.args[3]) or 0
local minpower = newradix ^ (precision * -1)
minpower = newradix ^ (precision * -1)
if decimal < minpower then
if decimal < minpower then
return "0"
return "0"
end
end
-- Weird radices
-- arrays of digits
-- If newradix is 1, just return decimal instead of erroring the formula
digits = {}
if math.abs(newradix) == 1 then return tostring(decimal) end
digitchars = {}
-- If newradix is negative it should use a different formulation; for now just do abs(newradix)
if newradix < 0 then newradix = math.abs(newradix) end
-- If newradix is nonintegral, character calculation is fucky, but probably fine
-- final string to yeet everything into
-- maxpower calculation
local ret = ""
maxpower = 1
while math.abs(maxpower) < math.abs(decimal) do
maxpower = maxpower * radix
end
-- if decimal < 0 then maxpower should be 1
local maxpower = 1
-- calculate digits
if decimal > 0 then
digitval = maxpower
    -- Get highest power of newradix less than decimal
i = 1
    while maxpower < decimal do
-- format radix and set up num of integral digits for possible formatting
    maxpower = maxpower * newradix
if radix > 0 then decimal = math.abs(decimal) end
    end
integrals = 0
    maxpower = maxpower / newradix
while math.abs(digitval) >= math.abs(minpower) do
   
-- get floor of abs(decimal) / abs (digitval)
    -- separate amount less than 1 and integer part (for separator function)
thisdigit = math.floor(math.abs(decimal) / math.abs(digitval))
    decimalpart = decimal - math.floor(decimal)
-- if i is 1 and thisdigit is 0:
    integralpart = math.floor(decimal)
-- if radix is negative, add 1 to thisdigit
   
-- if radix is positive and maxpower isn't 1, skip
    -- Double loop
add_digit = true
    -- Outer loop: While maxpower >= minpower, add result of second loop to ret
if thisdigit == 0 and i == 1 then
    -- Inner loop: While decimal >= maxpower, subtract maxpower from decimal
if radix < 0 then
    while maxpower >= minpower do
thisdigit = 1
    local digit = 1
elseif maxpower > 1 then
    while decimal >= maxpower do
add_digit = false
    decimal = decimal - maxpower
end
    digit = digit + 1
end
    end
if add_digit then
    -- digit now contains number of maxpowers
-- add thisdigit to digits
    -- IF DIGIT = RADIX: add 1 to previous digit and make current digit "0"
digits[i] = thisdigit
    if digit == newradix+1 then
-- subtract thisdigit * digitval from decimal
    if string.len(ret) > 0 then
decimal = decimal - (thisdigit * digitval)
    prevdigit = string.find(characters, string.sub(ret, -1, -1))[1]
if digitval >= 1 then integrals = integrals + 1 end
    ret = string.sub(ret, 1, -2) .. string.sub(characters, prevdigit+1, prevdigit+1)
digitval = digitval / radix
    digit = 1
i = i + 1
    else
end
    ret = ret .. "1"
    digit = 1
    end
    end
    ret = ret .. string.sub(characters, digit, digit)
   
    -- when maxpower hits 1:
    -- append a . if maxpower went below 1 and there is more to print
    -- run separator function on ret
    if maxpower == 1 then
    if format_output then ret = r.separator(ret, newradix) end
    if minpower < 1 then ret = ret .. "." end
    end
    maxpower = maxpower / newradix
    end
    return sign .. ret
else
-- Decimal is 0, also return itself
return tostring(decimal)
end
end
end
-- Meant for internal use only, adds "," between every 3-4 digits depending on radix
r.separator = function(cs, radix)
local dist = radix <= 6 and 3 or 4
local separator = dist == 3 and "," or " "
if string.len(cs) > dist then
-- assemble digits
local pos = dist + 1
separators = 0
while pos < string.len(cs) do
distance = math.abs(radix) <= 6 and 3 or 4
cs = string.sub(cs, 1, (pos*-1)-1) .. separator .. string.sub(cs, pos*-1)
for j,digit in ipairs(digits) do
pos = pos + dist + 2
digitchars[j+separators] = string.sub(characters, digit+1, digit+1)
-- when integrals - j is a positive multiple of distance
if format_output then
if j < integrals and (integrals - j) % distance == 0 then
-- add "," and 1 to separators
separators = separators + 1
digitchars[j+separators] = ","
end
end
-- when j equals integrals
if j == integrals then
-- add "." and 1 to separators
separators = separators + 1
digitchars[j+separators] = "."
end
end
end
end
return cs
-- if sign is -1, append a negative sign to the front
signchar = sign == -1 and "" or "-"
ret = "" .. signchar
-- assemble final number
for k,character in ipairs(digitchars) do
ret = ret .. character
end
end
end


return r
return r

Revision as of 18:51, 5 July 2026

Documentation for this module may be created at Module:Radix/doc

local r = {}

r.decimal_to = function(frame)
	-- Get number (in base 10)
	decimal = tonumber(frame.args[1])
	-- If decimal is 0 or 1, return decimal
	if decimal == 0 or decimal == 1 then 
		return tostring(decimal)
	end
	
	-- Do I use separators?
	format_output = format_output and format_output or true
	
	-- Get radix to convert to
	radix = tonumber(frame.args[2])
	-- sign is equal to sign(decimal) if radix is positive, and 1 otherwise
	sign = radix > 0 and decimal / math.abs(decimal) or 1
	-- If radix is not an integer: Round to nearest integer for now
	radix = radix < 0 and math.ceil(x) or math.floor(x)
	-- If abs(radix) is 1, 0, or > 36, return decimal 
	if radix == 0 or math.abs(radix) == 1 or math.abs(radix) > 36 then 
		return tostring(decimal)
	end
	
	-- characters are based on other proglangs' parsing
	characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
	
	-- precision is the number of digits below 1 to use
	-- if decimal is less than 1/newradix ^ precision, return 0
	precision = tonumber(frame.args[3]) or 0
	minpower = newradix ^ (precision * -1)
	if decimal < minpower then
		return "0"
	end
	
	-- arrays of digits
	digits = {}
	digitchars = {}
	
	-- maxpower calculation
	maxpower = 1
	while math.abs(maxpower) < math.abs(decimal) do
		maxpower = maxpower * radix
	end
	-- if decimal < 0 then maxpower should be 1
	
	-- calculate digits
	digitval = maxpower
	i = 1
	-- format radix and set up num of integral digits for possible formatting
	if radix > 0 then decimal = math.abs(decimal) end
	integrals = 0
	while math.abs(digitval) >= math.abs(minpower) do
		-- get floor of abs(decimal) / abs (digitval)
		thisdigit = math.floor(math.abs(decimal) / math.abs(digitval))
		-- if i is 1 and thisdigit is 0:
		-- if radix is negative, add 1 to thisdigit
		-- if radix is positive and maxpower isn't 1, skip
		add_digit = true
		if thisdigit == 0 and i == 1 then
			if radix < 0 then
				thisdigit = 1
			elseif maxpower > 1 then
				add_digit = false
			end
		end
		if add_digit then
			-- add thisdigit to digits
			digits[i] = thisdigit
			-- subtract thisdigit * digitval from decimal
			decimal = decimal - (thisdigit * digitval)
			if digitval >= 1 then integrals = integrals + 1 end
			digitval = digitval / radix
			i = i + 1
		end
	end
	
	-- assemble digits
	separators = 0
	distance = math.abs(radix) <= 6 and 3 or 4
	for j,digit in ipairs(digits) do
		digitchars[j+separators] = string.sub(characters, digit+1, digit+1)
		-- when integrals - j is a positive multiple of distance
		if format_output then
			if j < integrals and (integrals - j) % distance == 0 then
				-- add "," and 1 to separators
				separators = separators + 1
				digitchars[j+separators] = ","
			end
		end
		-- when j equals integrals
		if j == integrals then
			-- add "." and 1 to separators
			separators = separators + 1
			digitchars[j+separators] = "."
		end
	end
	
	-- if sign is -1, append a negative sign to the front
	signchar = sign == -1 and "" or "-"
	ret = "" .. signchar
	-- assemble final number
	for k,character in ipairs(digitchars) do
		ret = ret .. character
	end
end

return r