模組:Complex Number/Functions
外观
![]() | 此模块被引用於約12,000個頁面。 為了避免造成大規模的影響,所有對此模块的編輯應先於沙盒或測試樣例上測試。 測試後無誤的版本可以一次性地加入此模块中,但是修改前請務必於討論頁發起討論。 模板引用數量會自動更新。 |
本模組定義了一些可供Module:Complex_Number系列模組使用的擴充函數。
使用條件
要能使用此函數,必須先輸入一個數字類別資料結構以及其專用的math程式庫
- 數字類別資料結構必須包含下列成員函數:
- 專用的math程式庫必須包含下列成員:
使用方法
- 初始化任何符合此擴充函數庫使用條件的數學庫
local 自訂函數庫名稱 = require("Module:Complex Number").函數庫名稱.init()
- 以Module:Complex Number的cmath為例:
local cmath = require("Module:Complex Number").cmath.init()
- 以Module:Complex Number的cmath為例:
- 初始化本擴充函數庫
自訂函數庫名稱 = require("Module:Complex Number/Functions")._init(自訂函數庫名稱, 函數庫對應的數字建構函式)
- 以上述之Module:Complex Number的cmath為例:
cmath = require("Module:Complex Number/Functions")._init(cmath, cmath.constructor)
- 以上述之Module:Complex Number的cmath為例:
- 使用擴充函數庫中的函數
- 例如:
print(cmath.factorial(5), cmath.sec(cmath.pi/4))
- 輸出:120 1.4142135623731
- 例如:
模組中的函數
三角函數擴充
- 擴充了原本未定義的三角函數
- 功能
- 輸入一個複數x,回傳其指定三角函數的值
range(x,min,max)
- 功能
- 只取函數的某一段
- 若x位於min,max區間內,則回傳x,否則回傳NaN
統計函數
- 功能
- 輸入一系列數字,回傳其指定的統計值
diff(function, x0)
integral(a, b, function, step)
- 功能
- 輸入一個函數,計算從a到b的定積分,並以step為求黎曼和的間距
- 實作方式
- en:Boole's_rule
limit(x0, way, function)
- 功能
- 輸入一個函數,計算從way方向向x0逼近的極限。
- 其中,way=1為右極限、way=-1為左極限、way=0為不分方向的極限,若左極不等於右極回傳NaN
條件式
- 常數條件輸入
- if(條件, 為真時, 為假時)、ifelse(條件1, 條件1為真, 條件2, 條件2為真, ... ,皆為假)
- 代表條件在傳入函數時已經完成計算
- 函數條件輸入
- iff(條件函數, 為真時, 為假時)、ifelsef(條件函數1, 條件1為真, 條件函數2, 條件2為真, ... ,皆為假)
- 代表條件在傳入函數時尚未計算,判斷的當下才計算。所傳入的函數需要是無參數函數,若有參數也只會被忽略。用於定義遞迴下的條件
factorial(x)
binomial(n,k)
- 功能
- 計算二項式係數
- 也可以理解為從n個元素中取出k個元素的方法數
gcd(a,b,c,...)
lcm(a,b,c,...)
- 功能
- 計算a,b,c,....等數字的最小公倍數,支援複數。
- 實作方式
- 最小公倍數#计算方法
gamma(x)
- 功能
- 輸入一個複數x,回傳其Γ函數值

- 精確度
- 有效數字14位
- 運算效率
- 平均一次運算耗時約0.3582毫秒(3.6×10−4 s、一秒可計算2,700+次),測試於2018年11月19日 (一) 06:39 (UTC)、2022年4月12日 (二) 17:54 (UTC)。
- 實作方式
- 共分成4個部分
參考文獻
- ^ Wrench, J.W. (1968). Concerning two series for the gamma function. Mathematics of Computation, 22, 617–626. and
Wrench, J.W. (1973). Erratum: Concerning two series for the gamma function. Mathematics of Computation, 27, 681–682. - ^ Viktor T. Toth. "Programmable Calculators: Calculators and the Gamma Function". 2006. (原始内容存档于2007-02-23).
- ^ F. W. J. Olver, A. B. Olde Daalhuis, D. W. Lozier, B. I. Schneider, R. F. Boisvert, C. W. Clark, B. R. Miller, and B. V. Saunders, eds. NIST Digital Library of Mathematical Functions.
local p = {}
function p._init(_math_lib, _to_number)
local warp_funcs={"factorial","gamma","sec","csc","sech","csch","asec","acsc","asech","acsch","gd","cogd","arcgd",
"gcd"
}
for i=1,#warp_funcs do
_math_lib[ warp_funcs[i] ] = p['_' .. warp_funcs[i] ]
end
math_lib = _math_lib
to_number = _to_number
return _math_lib
end
function p._complex_number()
return p._init(require("Module:Complex Number").cmath.init(), require("Module:Complex Number").cmath.init().toComplexNumber)
end
function p._factorial(cal_z)return p._gamma(to_number(cal_z) + 1)end
function p._sec(cal_z)return math_lib.inverse( math_lib.cos( to_number(cal_z) ) )end
function p._csc(cal_z)return math_lib.inverse( math_lib.sin( to_number(cal_z) ) )end
function p._sech(cal_z)return math_lib.inverse( math_lib.cosh( to_number(cal_z) ) )end
function p._csch(cal_z)return math_lib.inverse( math_lib.sinh( to_number(cal_z) ) )end
function p._asec(cal_z)return math_lib.acos( math_lib.inverse( to_number(cal_z) ) )end
function p._acsc(cal_z)return math_lib.asin( math_lib.inverse( to_number(cal_z) ) )end
function p._asech(cal_z)return math_lib.acosh( math_lib.inverse( to_number(cal_z) ) )end
function p._acsch(cal_z)return math_lib.asinh( math_lib.inverse( to_number(cal_z) ) )end
function p._gd(cal_z)return math_lib.atan( math_lib.tanh( to_number(cal_z) * 0.5 ) ) * 2 end
function p._arcgd(cal_z)return math_lib.atanh( math_lib.tan( to_number(cal_z) * 0.5 ) ) * 2 end
function p._cogd(cal_z)local x = to_number(cal_z); return - math_lib.sgn( x ) * math_lib.log( math_lib.abs( math_lib.tanh( x * 0.5 ) ) ) end
local function fold(func, ...)
-- Use a function on all supplied arguments, and return the result. The function must accept two numbers as parameters,
-- and must return a number as an output. This number is then supplied as input to the next function call.
local vals = {...}
local count = #vals -- The number of valid arguments
if count == 0 then return
-- Exit if we have no valid args, otherwise removing the first arg would cause an error.
nil, 0
end
local ret = table.remove(vals, 1)
for _, val in ipairs(vals) do
ret = func(ret, val)
end
return ret, count
end
--[[
Fold arguments by selectively choosing values (func should return when to choose the current "dominant" value).
]]
local function binary_fold(func, ...)
local value = fold((function(a, b) if func(a, b) then return a else return b end end), ...)
return value
end
local Reciprocal_gamma_coeff = {1,0.577215664901532860607,-0.655878071520253881077,-0.0420026350340952355290,0.166538611382291489502,-0.0421977345555443367482,-0.00962197152787697356211,0.00721894324666309954240,-0.00116516759185906511211,-0.000215241674114950972816,0.000128050282388116186153,-0.0000201348547807882386557,-1.25049348214267065735e-6,1.13302723198169588237e-6,-2.05633841697760710345e-7,6.11609510448141581786e-9,5.00200764446922293006e-9,-1.18127457048702014459e-9,1.04342671169110051049e-10,7.78226343990507125405e-12,-3.69680561864220570819e-12,5.10037028745447597902e-13,-2.05832605356650678322e-14,-5.34812253942301798237e-15,1.22677862823826079016e-15,-1.18125930169745876951e-16,1.18669225475160033258e-18,1.41238065531803178156e-18,-2.29874568443537020659e-19,1.71440632192733743338e-20}
local stirling_series_coeff = {1,0.083333333333333333333,0.0034722222222222222222,-0.0026813271604938271605,-0.00022947209362139917695,0.00078403922172006662747,0.000069728137583658577743,-0.00059216643735369388286,-0.000051717909082605921934,0.00083949872067208727999,0.000072048954160200105591,-0.0019144384985654775265, -0.00016251626278391581690}
function p._gamma_high_imag(cal_z)
local z = to_number(cal_z)
if z ~= nil and math_lib.abs(math_lib.nonRealPart(z)) > 1 then
local inv_z = math_lib.inverse(z)
return math_lib.sqrt((math_lib.pi * 2) * inv_z) * math_lib.pow(z * math_lib.exp(-1) *
math_lib.sqrt( (z * math_lib.sinh(inv_z) ) + math_lib.inverse(to_number(810) * z * z * z * z * z * z) ),z)
end
return nil
end
function p._gamma_morethen_lua_int(cal_z)
local z = to_number(cal_z) - to_number(1)
local lua_int_term = 18.1169 --FindRoot[ Factorial[ x ] == 2 ^ 53, {x, 20} ]
if math_lib.abs(z) > (lua_int_term - 1) or (math_lib.re(z) < 0 and math_lib.abs(math_lib.nonRealPart(z)) > 1 ) then
local sum = 1
for i = 1, #stirling_series_coeff - 1 do
local a, n = to_number(z), tonumber(i) local y, k, f = to_number(1), n, to_number(a)
while k ~= 0 do
if k % 2 == 1 then y = y * f end
k = math.floor(k / 2); f = f * f
end
sum = sum + stirling_series_coeff[i + 1] * math_lib.inverse(y)
end
return math_lib.sqrt( (2 * math.pi) * z ) * math_lib.pow( z * math.exp(-1), z ) * sum
end
return nil
end
function p._gamma_abs_less1(cal_z)
local z = to_number(cal_z)
if math_lib.abs(z) <=1.001 then
if math_lib.abs(math_lib.nonRealPart(z)) < 1e-14 and ( (math.abs(math_lib.re(z) - 1) < 1e-14) or (math.abs(math_lib.re(z) - 2) < 1e-14) ) then return to_number(1)end
return math_lib.inverse(p._recigamma_abs_less1(z))
end
return nil
end
function p._recigamma_abs_less1(z)
local result = to_number(0)
for i=1,#Reciprocal_gamma_coeff do
result = result + Reciprocal_gamma_coeff[i] * math_lib.pow(z,i)
end
return result
end
function p._gamma(cal_z)
local z = to_number(cal_z)
if math_lib.abs(math_lib.nonRealPart(z)) < 1e-14 and ((math_lib.re(z) < 0 or math.abs(math_lib.re(z)) < 1e-14)
and math.abs(math.floor(math_lib.re(z)) - math_lib.re(z)) < 1e-14 ) then return tonumber("nan") end
local pre_result = p._gamma_morethen_lua_int(z) or p._gamma_high_imag(z) or p._gamma_abs_less1(z)
if pre_result then return pre_result end
local real_check = math_lib.re(z)
local loop_count = math.floor(real_check)
local start_number, zero_flag = z - loop_count, false
if math_lib.abs(start_number) <= 1e-14 then start_number = to_number(1);zero_flag = true end
local result = math_lib.inverse(p._recigamma_abs_less1(start_number))
if math_lib.abs(math_lib.nonRealPart(z)) < 1e-14 and ((math_lib.re(z) > 1e-14 )and math.abs(math.floor(math_lib.re(z)) - math_lib.re(z)) < 1e-14 ) then result = to_number(1) end
local j = to_number(start_number)
for i=1,math.abs(loop_count) do
if loop_count > 0 then result = result * j else result = result * math_lib.inverse(j-1) end
if zero_flag==true and loop_count > 0 then zero_flag=false else if loop_count > 0 then j = j + 1 else j = j - 1 end end
end
if math_lib.abs(math_lib.nonRealPart(z)) < 1e-14 and ((math_lib.re(z) > 1e-14 )and math.abs(math.floor(math_lib.re(z)) - math_lib.re(z)) < 1e-14 ) then return math_lib.floor(result) end
return result
end
function p._gcd(...)
local function findGcd(a, b)
local r, oldr = to_number(b), to_number(a)
while math_lib.abs(r) > 1e-6 do local mod_val = oldr % r oldr, r = to_number(r), mod_val end
if math_lib.abs(math_lib.nonRealPart(oldr)) < 1e-14 and (math_lib.re(oldr) < 0 ) then oldr = -oldr end
return oldr
end
local result, count = fold(findGcd, ...)
return result
end
return p