模块:NumSysConvert

来自「荏苒之境」
Sicusa留言 | 贡献2025年8月11日 (一) 23:06的版本

此模块的文档可以在模块:NumSysConvert/doc创建

local utils_str = require("Module:Utils/String")

local num_sys_convert = {}

local DIGIT_MAP = {
	"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
	"A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
	"K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
	"U", "V", "W", "X", "Y", "Z"
}

local function decimal_to_base(input_num, target_base, digit_map, max_precision)
	digit_map = digit_map or DIGIT_MAP
	local digit_len = #digit_map
	
    if target_base < 2 or target_base > digit_len then
        error("根据您的映射表长度,目标进制只支持2~"..digit_len.."进制")
    elseif input_num == 0 then
    	return "0"
    end
    
    max_precision = max_precision or 10
    
    local is_negative = input_num < 0
    input_num = math.abs(input_num)
    
    local integer_part = math.floor(input_num)
    local integer_result = ""
    local fractional_part = input_num - integer_part
    local fractional_result = ""
    
    if integer_part == 0 then
        integer_result = "0"
    else
        while integer_part > 0 do
            local remainder = integer_part % target_base
            integer_result = digit_map[remainder + 1]..integer_result
            integer_part = math.floor(integer_part / target_base)
        end
    end
    
    if fractional_part > 0 then
        fractional_result = "."
        local precision_count = 0
        
        while fractional_part > 0 and precision_count < max_precision do
            fractional_part = fractional_part * target_base
            local current_digit = math.floor(fractional_part)
            fractional_result = fractional_result..digit_map[current_digit + 1]
            fractional_part = fractional_part - current_digit
            precision_count = precision_count + 1
        end
    end
    
    local final_result = integer_result..fractional_result
    if is_negative then
        final_result = "-"..final_result
    end
    return final_result
end

num_sys_convert.decimal_to_base = decimal_to_base

num_sys_convert.show = function(frame)
	local dec_str = string.gsub(frame.args.num, ",", "")
	local num = tonumber(dec_str)
	local base = tonumber(frame.args.base)
	local digit_map = frame.args.digit_map
	return decimal_to_base(num, base,
		digit_map ~= nil and digit_map ~= "" and digit_map or DIGIT_MAP)
end

return num_sys_convert