Module:FunctionGraph:修订间差异
外观
删除的内容 添加的内容
无编辑摘要 |
无编辑摘要 |
||
第3行: | 第3行: | ||
local getArgs = require('Module:Arguments').getArgs |
local getArgs = require('Module:Arguments').getArgs |
||
local lib_calc = require('Module:Complex_Number/Calculate') |
local lib_calc = require('Module:Complex_Number/Calculate') |
||
local TrackingCategory = require('Module:TrackingCategory') |
|||
function p.functionGraph(frame) |
function p.functionGraph(frame) |
2022年7月15日 (五) 14:18的版本
函數
functionGraph
一般函數圖形
{{#invoke:FunctionGraph|functionGraph|sin(x)|start=-5|end=5}}
由于已知的技术原因,图表暂时不可用。带来不便,我们深表歉意。
complex_graph
複變函數圖形(色相環複變函數圖形)。因要向2個維度取樣(如取樣數設定為100則要運算100×100=10000次,更高的取樣數可能會超出WP:模板限制)因此較耗費效能,請斟酌使用。
{{#invoke:FunctionGraph|complex_graph|x}}
- 脚本错误:函数“complex_graph”不存在。
{{#invoke:FunctionGraph|complex_graph|sin(1/x)|xstart=-0.5|xend=0.5|ystart=-0.5|yend=0.5}}
- 脚本错误:函数“complex_graph”不存在。
local p = {}
local comp_number = nil
local getArgs = require('Module:Arguments').getArgs
local lib_calc = require('Module:Complex_Number/Calculate')
local TrackingCategory = require('Module:TrackingCategory')
function p.functionGraph(frame)
if comp_number == nil then comp_number = require("Module:Complex Number") end
local cmath, qmath = comp_number.cmath.init(), comp_number.qmath.init()
if not getArgs then getArgs = require('Module:Arguments').getArgs end
local args = getArgs(frame, {parentFirst=true})
local exprs = {}
local body_args, x_start, x_end, y_min, y_max, sampling = {}, 0, 1, nil, nil, 50
for arg_name, arg_value in pairs( args ) do
if tonumber(arg_name) ~= nil then exprs[#exprs + 1] = lib_calc._remove_strip_marker(arg_value)
elseif mw.ustring.lower(arg_name) == "start" then x_start = tonumber(arg_value)
elseif mw.ustring.lower(arg_name) == "end" then x_end = tonumber(arg_value)
elseif mw.ustring.lower(arg_name) == "sampling" then sampling = tonumber(arg_value)
elseif mw.ustring.lower(arg_name) == "min" then y_min = tonumber(arg_value)
elseif mw.ustring.lower(arg_name) == "max" then y_max = tonumber(arg_value)
else body_args[arg_name] = arg_value
end
end
local yesno = require('Module:Yesno')
if yesno(args.useOtherModule or 'no') == true then lib_calc.use_other_module = true end
local body = p._functionGraph(exprs,
x_start, x_end, sampling, y_min, y_max, body_args, ( {
cmath = cmath,
qmath = qmath,
} ) [ frame.args['class'] ] , (( {
cmath = cmath.toComplexNumber,
qmath = qmath.toQuaternionNumber,
} ) [ frame.args['class'] ] ) )
body.width = 400
body.height = 100; body.type="line"
body.interpolate = frame.args['interpolate'] or "monotone"
for arg_name, arg_value in pairs( body_args ) do
body[arg_name] = arg_value
end
body = mw.getCurrentFrame():expandTemplate{title = "Graph:Chart", args = body}
if use_ext_mathlib == true then TrackingCategory.append('使用擴充複變函數庫的頁面') end
return body
end
function p.calc_table(frame)
local variable_process = require("Module:Number/data")
local args
local can_math = false
local should_math = false
local show_math = false
if frame == mw.getCurrentFrame() then
-- We're being called via #invoke. The args are passed through to the module
-- from the template page, so use the args that were passed into the template.
args = getArgs(frame, {
parentFirst=true,
trim = false,
removeBlanks = false
}) --frame.args
local yesno = require('Module:Yesno')
can_math = yesno(args['use math'] or args['use_math'])
should_math = yesno(args['should math'] or args['should_math'])
else
-- We're being called from another module or from the debug console, so assume
-- the args are passed in directly.
args = frame
end
lib_calc._randomseed()
local yesno = require('Module:Yesno')
if yesno(args.useOtherModule or 'no') == true then lib_calc.use_other_module = true end
local first_number_list = {"2","3","4","5","6","7","8","9"}
local second_number_list, first_number_show, second_number_show
local calculate_str, calculate_title = "{{{left}}} * {{{right}}}", "×"
if args['number list'] or args['number_list'] then first_number_list = mw.text.split(args['number list'] or args['number_list'] or '',',') end
if args['number list2'] or args['number_list2'] then second_number_list = mw.text.split(args['number list2'] or args['number_list2'] or '',',') end
if args['number list show'] or args['number_list_show'] then
first_number_show = mw.text.split(args['number list show'] or args['number_list_show'] or '',',')
if #first_number_show == 1 and mw.text.trim(first_number_show[1]) == '' then first_number_show = {} end
end
if args['number list show2'] or args['number_list_show2'] then
second_number_show = mw.text.split(args['number list show2'] or args['number_list_show2'] or '',',')
if #second_number_show == 1 and mw.text.trim(second_number_show[1]) == '' then second_number_show = {} end
end
if args['calculate'] then calculate_str = mw.text.trim(lib_calc._remove_strip_marker(args['calculate'])) end
if args['calculate title'] or args['calculate_title'] then calculate_title = mw.text.trim(args['calculate title'] or args['calculate_title']) end
if second_number_list == nil or (second_number_list and (second_number_list == {} or #second_number_list == 0) ) then
second_number_list = first_number_list
end
if first_number_show == nil or (first_number_show and (first_number_show == {} or #first_number_show == 0) ) then
first_number_show = first_number_list
end
if second_number_show == nil or (second_number_show and (second_number_show == {} or #second_number_show == 0) ) then
second_number_show = first_number_show
end
local body, buffer_str, table_str = "", '', ''
if comp_number == nil then comp_number = require("Module:Complex Number") end
local cmath, qmath, bmath = comp_number.cmath.init(), comp_number.qmath.init(), comp_number.bmath.init()
local mathtag = lib_calc.tagmath.init()
local math_class = args['class']or''
if mw.text.trim(math_class) == '' then math_class = "cmath" end
local mymath = cmath
local mytomath = cmath.toComplexNumber
if mw.ustring.sub(math_class,1,7):upper()=="MODULE:" then
local module_name, math_lib_name = lib_calc.checkModuleClass(math_class)
xpcall(function()
local load_module = require("Module:"..module_name)
if load_module ~= nil then
local load_math_lib = load_module[math_lib_name]
if load_module ~= nil then
local func_type = type(function()end)
local my_math_lib = (type(load_math_lib.init) == func_type) and load_math_lib.init() or load_math_lib
if type(my_math_lib.constructor) == func_type then
math_class = "mymath"
mymath = my_math_lib
mytomath = my_math_lib.constructor
end
end
end
end,function()end)
end
body = body .. "! " .. (args["main head css"] or args["main_head_css"] or '') .. " | " .. calculate_title .. ' \n'
for j=1,#second_number_list do
local second_it = mw.text.trim(second_number_list[j] or '')
local second_it_show = mw.text.trim(second_number_show[j] or '')
if second_it ~= nil then
local second_num_math = tostring(second_it_show or second_it)
if should_math or can_math then
if args.class ~= "mathtag" and yesno(args['show math'] or args['show_math']) then
second_num_math = _re_math_output(second_num_math)
end
second_num_math = _adj_math_output(second_num_math)
end
if can_math then second_num_math = frame:callParserFunction{name = "#tag:math", args = {second_num_math}} end
body = body .. "! " .. (args["head css"] or args["head_css"] or '') .. " | " .. second_num_math .. ' \n'
end
end
body = body .. '\n'
for i=1,#first_number_list do
local first_it = mw.text.trim(first_number_list[i] or '')
local first_it_show = mw.text.trim(first_number_show[i] or '')
if first_it ~= nil then
body = body .. "|-\n"; table_str = ''
local first_num_math = tostring(first_it_show or first_it)
if should_math or can_math then
if args.class ~= "mathtag" and yesno(args['show math'] or args['show_math']) then
first_num_math = _re_math_output(first_num_math)
end
first_num_math = _adj_math_output(first_num_math)
end
if can_math then first_num_math = frame:callParserFunction{name = "#tag:math", args = {first_num_math}} end
body = body .. "! " .. (args["head css"] or args["head_css"] or '') .. " | " .. first_num_math .. " \n"
for j=1,#second_number_list do
local second_it = mw.text.trim(second_number_list[j] or '')
if second_it ~= nil then
buffer_str = variable_process._getFormatingStringByArgument(calculate_str, {
left=tostring(first_it),right=tostring(second_it)
})
local exec_result = lib_calc.calc( buffer_str or '', ( {
cmath = cmath,
qmath = qmath,
bmath = bmath,
mathtag = mathtag,
mymath = mymath
} ) [ math_class ] , (( {
cmath = cmath.toComplexNumber,
qmath = qmath.toQuaternionNumber,
bmath = bmath.toBoolean,
mathtag = mathtag.toTagMath,
mymath = mytomath
} ) [ math_class ] ) )
local exec_result_str = mw.text.trim(tostring(exec_result) or '')
local exec_check = mw.text.trim((tonumber(exec_result_str) and args[tonumber(exec_result_str)]) or args[exec_result_str] or '')
if exec_check == '' then exec_check = nil end
table_str = table_str .. '|' .. (exec_check or args["number css"] or args["number_css"] or '') .. "| "
if should_math or can_math then
if args.class ~= "mathtag" and yesno(args['show math'] or args['show_math']) then
exec_result_str = _re_math_output(exec_result_str)
end
exec_result_str = _adj_math_output(exec_result_str)
end
if can_math then exec_result_str = frame:callParserFunction{name = "#tag:math", args = {exec_result_str}} end
table_str = table_str .. mw.text.trim(exec_result_str) .. ' \n'
end
end
body = body .. table_str
end
end
if use_ext_mathlib == true then TrackingCategory.append('使用擴充複變函數庫的頁面') end
return body
end
function p._functionGraph(expr_arr,x_start,x_end,sampling, y_min, y_max, body_args, math_lib, number_Constructer)
if (yesno or require('Module:Yesno'))((body_args or {}).useOtherModule or 'no') == true then lib_calc.use_other_module = true end
if comp_number == nil then comp_number = require("Module:Complex Number") end
math = comp_number.math.init()
lib_calc._randomseed()
local mathlib, numberConstructer = math_lib or math, number_Constructer or tonumber
local postfix = {}
local check_func = {}
local x_arr, y_arr = {}, {}
if type(expr_arr) == type({}) then
for i=1,#expr_arr do
local check_parametric = mw.text.split(expr_arr[i],';')
if #check_parametric == 1 then
local pre_expr, pre_scope = lib_calc._function_preprocessing(expr_arr[i], mathlib, numberConstructer, false)
postfix[#postfix + 1] = lib_calc.infixToPostfix(pre_expr, debug_flag)
if pre_scope then postfix[#postfix].scope = pre_scope end
elseif #check_parametric >= 3 then
postfix[#postfix + 1]={parametric=true}
postfix[#postfix].x_name = check_parametric[1] or 't'
postfix[#postfix].y_name = check_parametric[2] or 't'
postfix[#postfix].x = lib_calc.infixToPostfix(check_parametric[1] or 't', debug_flag)
postfix[#postfix].y = lib_calc.infixToPostfix(check_parametric[2] or 't', debug_flag)
postfix[#postfix].t = check_parametric[3] or 't'
postfix[#postfix].min = numberConstructer(check_parametric[4]) or numberConstructer(0)
postfix[#postfix].max = numberConstructer(check_parametric[5]) or numberConstructer(1)
end
y_arr[#y_arr + 1] = {}
x_arr[#x_arr + 1] = {}
end
else
local check_parametric = mw.text.split(expr_arr,';')
if #check_parametric == 1 then
local pre_expr, pre_scope = lib_calc._function_preprocessing(expr_arr, mathlib, numberConstructer, false)
postfix[#postfix + 1] = lib_calc.infixToPostfix(pre_expr, debug_flag)
if pre_scope then postfix[#postfix].scope = pre_scope end
elseif #check_parametric >= 3 then
postfix[#postfix + 1]={parametric=true}
postfix[#postfix].x_name = check_parametric[1] or 't'
postfix[#postfix].y_name = check_parametric[2] or 't'
postfix[#postfix].x = lib_calc.infixToPostfix(check_parametric[1] or 't', debug_flag)
postfix[#postfix].y = lib_calc.infixToPostfix(check_parametric[2] or 't', debug_flag)
postfix[#postfix].t = check_parametric[3] or 't'
postfix[#postfix].min = numberConstructer(check_parametric[4]) or numberConstructer(0)
postfix[#postfix].max = numberConstructer(check_parametric[5]) or numberConstructer(1)
end
y_arr[#y_arr + 1] = {}
x_arr[#x_arr + 1] = {}
end
local check_cexpr = mw.title.new("cexpr","template"):getContent()
local check_isreal = mw.title.new("isReal","template"):getContent()
local check_ifNumeric = mw.title.new("ifNumeric","template"):getContent()
for i=0,sampling do
local it = x_start + (i * (x_end-x_start) / sampling)
local x_val = it
for j=1,#expr_arr do
local calc_val = " "
xpcall(function()
if type(postfix[j]) == type({}) and postfix[j].parametric == true then
local it_t = postfix[j].min + (i * (postfix[j].max - postfix[j].min) / sampling)
--參數式
calc_val = lib_calc.calc_by_postfix(postfix[j].y, {[postfix[j].t]=it_t}, mathlib, numberConstructer, false)
x_val = lib_calc.calc_by_postfix(postfix[j].x, {[postfix[j].t]=it_t}, mathlib, numberConstructer, false)
else
calc_val = lib_calc.calc_by_postfix(postfix[j], {
x=it,
last=function(num) --for Template:數列
local last_num = (body_args or {})['last' .. tonumber(tostring(num or 1))] or 0
return numberConstructer(y_arr[j][#(y_arr[j])-(tonumber(tostring(num))or 1)+1] or last_num)
end,
}, mathlib, numberConstructer, false)
if( tonumber((body_args or {})["calc diff " .. tostring(j) ]) == 1 or ((yesno or require('Module:Yesno'))((body_args or {})["calc diff " .. tostring(j) ]or'no')==true) )then
local dy = lib_calc.calc_by_postfix(postfix[j], {x=(it + 1e-6)}, mathlib, numberConstructer, false)
calc_val = 1e6 * (dy - calc_val)
end
end
if y_max and mathlib.re(calc_val) > y_max then calc_val = y_max end
if y_min and mathlib.re(calc_val) < y_min then calc_val = y_min end
if x_end and mathlib.re(x_val) > x_end then x_val = x_end end
if x_start and mathlib.re(x_val) < x_start then x_val = x_start end
end,function(_)end)
if tonumber((body_args or {})["round number"]) ~= nil then
if calc_val then
calc_val = mathlib.round(calc_val, tonumber((body_args or {})["round number"]), 10)
end
end
if tonumber((body_args or {})["nonreal is nan"]) == 1 then
if math.abs(tonumber(mathlib.abs(mathlib.nonRealPart(calc_val))) or 0) > 1e-14 then calc_val = nil end
end
local num_check = mw.ustring.lower(tostring(numberConstructer(calc_val)))
if mw.ustring.match(num_check,"nan") or mw.ustring.match(num_check,"nil") or mw.ustring.match(num_check,"inf") then calc_val = ' ' end
num_check = mw.ustring.lower(tostring(numberConstructer(x_val)))
if mw.ustring.match(num_check,"nan") or mw.ustring.match(num_check,"nil") or mw.ustring.match(num_check,"inf") then x_val = ' ' end
y_arr[j][ (#(y_arr[j]) + 1) ] = tostring(calc_val)
x_arr[j][ (#(x_arr[j]) + 1) ] = tostring(x_val)
end
end
local result={}
if #expr_arr > 0 then result.legend = "函數" end
for i=1,#expr_arr do
result['x'] = table.concat(x_arr[i],',')
result['y' .. tostring(i)] = table.concat(y_arr[i],',')
result['y' .. tostring(i) .. "Title"] = tostring( (body_args or {})[tostring(i) .. " name" ] or expr_arr[i] )
if type(postfix[i]) == type({}) and postfix[i].parametric == true then
result['y' .. tostring(i) .. "Title"] = "x=" .. postfix[i].x_name .. "; y=" .. postfix[i].y_name
elseif( tonumber((body_args or {})["calc diff " .. tostring(i) ]) == 1 )then
result['y' .. tostring(i) .. "Title"] = '( ' .. result['y' .. tostring(i) .. "Title"] .. " )\'"
end
if check_func[ result['y' .. tostring(i) .. "Title"] ] ~= nil then
local new_name = result['y' .. tostring(i) .. "Title"] .. " ,(" .. tostring(check_func[ result['y' .. tostring(i) .. "Title"] ]+1) .. ")"
check_func[ result['y' .. tostring(i) .. "Title"] ] = check_func[ result['y' .. tostring(i) .. "Title"] ] + 1
result['y' .. tostring(i) .. "Title"] = new_name
else check_func[ result['y' .. tostring(i) .. "Title"] ] = 1
end
end
return result
end
return p