模組:Complex Number/Calculate
外观
![]() | 此模块被引用於約12,000個頁面。 為了避免造成大規模的影響,所有對此模块的編輯應先於沙盒或測試樣例上測試。 測試後無誤的版本可以一次性地加入此模块中,但是修改前請務必於討論頁發起討論。 模板引用數量會自動更新。 |
![]() | 此模块使用Lua语言: |
本模組定義了一些數學運算的結構與邏輯。
使用方法
項目 | 語法 | 說明 | 範例 |
---|---|---|---|
數字的表達 |
|
數字的表達可分為實數表達、科學記號和含單位的數。
|
|
四則運算與冪運算 | 運算式運算符運算式
|
依序以中綴表示法表達運算式即可。 | 2+3*5^2 →脚本错误:函数“templateCalculate”不存在。
|
函數 | 函數 (參數1,參數2 ...)
|
调用现有函数。所有函數都至少要傳入一個參數。 | factorial(5) →脚本错误:函数“templateCalculate”不存在。
|
多組運算 | 運算式1;運算式2
|
僅會顯示最後一組運算的結果 | 2+3;2*3 →脚本错误:函数“templateCalculate”不存在。
|
變數定義 | 變數名稱←運算式
|
給特定名稱的變數賦值。需特別注意所有變數的範圍(Scope)皆相同(可想像所有變數皆為全域變數),包括函數中的參數,因此若函數外層已經定義了變數x則函數內部需避免使用同名變數x。 | x←5;x →脚本错误:函数“templateCalculate”不存在。
|
函數定義 | 函數名稱:參數1,參數2 ...↦函數運算式;
|
函數的語法為以名稱起始並以冒號區隔函數名稱與定義(函數名稱可留空,但冒號不能省去),整個語法要以分號(; )結尾。位於映射符號(↦ )前方為函數的變數或參數,後方為函數主體定義,即 f : x ↦ f (x) ; 。函數可以有多個變數,但僅能有單個輸出,即或。同時函數語法不建議寫成嵌套結構,即不建議將函數定義內包含另一個函數的定義,但可以分開定義再行組合;此外,函數定義內不能包含分號,因為分號會視為函數的結尾。
|
f:x↦x^2+1;(0);f(5) →脚本错误:函数“templateCalculate”不存在。
|
運算符優先序調整 | (運算式要優先計算的運算符運算式)運算符運算式
|
使用括號來令特定運算優先進行。 |
|
運算符
語法 | 名稱 | 元數 | 說明 | 優先 | 範例 | 效果 | math輸出 |
---|---|---|---|---|---|---|---|
基礎算术 | |||||||
e |
2 | 當e左鄰一實數、右鄰一整數時,則為科學記號,以 256e-3 為例,其代表的結果為。要注意的是左邊的數必為單一實數、右邊的數必為整數,可為負數,且中間不能有空格。 |
∞ | 12.3e4 |
|||
() |
1 | 改變運算優先順序 |
∞ | 2*(2+3) |
10 |
||
布尔代数 | |||||||
and |
2 | 邏輯且的字母模式。使用時須與前後文各間隔至少一個空格 |
5 | (1=1) and (1=2) |
|||
nand |
2 | 邏輯與非的字母模式。使用時須與前後文各間隔至少一個空格 |
5 | (1=1) nand (1=2) |
|||
or |
2 | 邏輯或的字母模式。使用時須與前後文各間隔至少一個空格 |
4 | (1=1) or (1=2) |
|||
nor |
2 | 邏輯或非的字母模式。使用時須與前後文各間隔至少一個空格 |
4 | (1=1) nor (1=2) |
|||
xor |
2 | 邏輯異或的字母模式。使用時須與前後文各間隔至少一個空格 |
4 | (1=1) xor (1=2) |
|||
xnor |
2 | 邏輯若且唯若的字母模式。使用時須與前後文各間隔至少一個空格 |
4 | (1=1) xnor (1=2) |
|||
not |
1 | 邏輯非的字母模式。使用時須與前後文各間隔至少一個空格 |
13 | not (1=2) |
|||
数值修约 | |||||||
round |
2 | round 的運算子模式,會將一數四捨五入到指定的位數。使用時須與前後文各間隔至少一個空格 |
8 | π round 6 |
|||
複變 | |||||||
i |
1 | 表達純虛數 |
∞ | 3i |
3i |
||
技術性 | |||||||
return |
1 | 返回數值。需注意return後方必須跟著一個數值或表達式,否則會變成未定義行為而出現預期外的結果。 |
2 | return 7;8 |
|||
三角函数 | |||||||
° |
1 | 用於表示角度單位的符號。 |
10 | 180° |
|||
π |
1 | 表示圓周率。 |
10 | 3π |
- 註:另有
>=
、<=
、==
(相等判斷)、~=
(不相等判斷)、!=
(不相等判斷)、@=
(數值指派)、+=
(相加指派)、-=
(相減指派)、*=
(相乘指派)、/=
(相除指派)、^=
(冪指派)、&=
(邏輯與指派)、|=
(邏輯或指派)可供使用,其會自動替換為上表中對應的運算元。指派運算元須注意等號左邊必須是一個單一變數詞語,不可以是括弧或函數變換的結果。
常數和數值
語法 | 名稱 | 別名 | 說明 | 數值 | math輸出 |
---|---|---|---|---|---|
e |
自然底數 | 自然對數函數的底數 | 2.718281828459 | ||
i |
虛數單位 | 表達純虛數 | i | ||
j |
四元數單位j | 表達純四元數虛數j | |||
k |
四元數單位k | 表達純四元數虛數k | |||
nan |
非數 | 用於表示數學上未定義的數值,或計算發生錯誤的數值。 | nan | ||
nil |
空值 | null |
空值。在math模式下顯示為空白,用於表達或傳遞無參數的函數之參數。請注意,由於此值為空值,因此請勿將此值參與運算,以免發生錯誤。 | ||
° |
角度單位 | 用於表示角度單位的符號。 | |||
π |
圓周率 | pi |
表示圓周率。 | 3.1415926535898 | |
ω |
艾森斯坦整数單位 | 表達艾森斯坦整数單位。 |
函數
語法 | 名稱 | 參數 數量 |
說明 | 範例 | 效果 | math輸出 |
---|---|---|---|---|---|---|
基礎算术 | ||||||
div |
2 | 用於在math輸出時,以分數的形式顯示 |
div(7,3) |
2.3333333333333 |
||
dot |
2 | 計算兩數的內積。 |
dot(7,3) |
21 |
||
pow |
2 | 計算兩數之冪運算 |
pow(7,3) |
343 |
||
数论 | ||||||
gcd |
不定 | 計算多個數的最大公因數。 |
gcd(7,21) |
7 |
||
lcm |
不定 | 計算多個數的最小公倍數。 |
lcm(7,3,21) |
21 |
||
digits |
1 | 取得整數的位數個數 |
digits(7321) |
4 |
||
divisor |
2 | 取得某數的第n個正因數 |
divisor(6,1),divisor(6,2),divisor(6,3),divisor(6,4) |
, |
||
primedivisor |
2 | 取得某數的第n個質因數 |
primedivisor(210,1),primedivisor(210,2),primedivisor(210,3),primedivisor(210,4) |
, |
||
divisorsigma |
2 | 計算特定整數的除數函數 |
divisorsigma(1,6) |
12 |
||
eulerphi |
1 | 取得小於等於n的正整數中與n互質的數的數目 |
eulerphi(8) |
|||
findnext |
向後尋找
|
2 | 尋找下一個符合條件的整數 |
findnext(:x↦x % 6 = 0;,6) |
||
findlast |
向前尋找
|
2 | 尋找前一個符合條件的整數 |
findlast(:x↦x % 6 = 0;,10) |
||
初等函數 | ||||||
abs |
1 | 計算一數與原點的歐幾里得距離 |
abs(-3) |
3 |
||
log |
1 | log(e) |
1 |
|||
log |
2 | log(2,16) |
4 |
|||
sgn |
1 | sgn(-7) |
-1 |
|||
sqrt |
1 | 計算一數的主平方根值 |
sqrt(16) |
4 |
||
inverse |
1 | inverse(7) |
0.14285714285714 |
|||
exp |
1 | exp(π⋅i) |
||||
数值修约 | ||||||
floor |
1 | 向下取整 |
floor(7.3) |
7 |
||
ceil |
1 | 向上取整 |
ceil(7.3) |
8 |
||
round |
3 | 對一數進行四捨五入。第一參數為欲四捨五入的數字;第二參數為欲四捨五入的位數;第三參數為當數值修約底數非十進制時的底數。 |
round(π,6) |
3.141593 |
||
trunc |
2 | 對一數取截尾函數。第一參數為欲截尾的數字;第二參數為欲截尾的位數。 |
trunc(π,6) |
3.141592 |
||
特殊函數 | ||||||
binomial |
2 | 計算二項式係數。亦可以被理解為從n個相異元素中取出k個元素的方法數。 |
binomial(7,3) |
35 |
||
factorial |
1 | 計算一數的階乘 |
factorial(7) |
5040 |
||
gamma |
1 | 計算一數的Γ函数 |
gamma(7) |
720 |
||
LambertW |
2 | 計算一數的朗伯W函数 |
LambertW(1) |
0.56714329040978 |
||
代数 | ||||||
norm |
2 | 計算一數或向量的範數 |
norm(3+4i,2) |
5 |
||
summation |
3 | 計算以函數表達之數列的總和。第一參數為數列首項;第二參數為數列末項;第三參數為用以表達數列的函數 |
summation(1,5,:x↦x^2;) |
|||
product |
3 | 計算以函數表達之數列的連乘積。第一參數為數列首項;第二參數為數列末項;第三參數為用以表達數列的函數 |
product(1,5,:it↦it;) |
|||
<不定> |
不定 | 调用自行定义的函数,這些函數通常是或。以 f:x↦x^2;;f(5) 為例,其中f:x↦x^2; 定義了函數,並调用了函数。函數的語法為以名稱起始並以冒號區隔函數名稱與定義(函數名稱可留空,但冒號不能省去),整個語法要以分號(; )結尾。位於映射符號(↦ )前方為函數的變數或參數,後方為函數主體定義。函數可以有多個變數,但僅能有單個輸出;同時函數語法不建議使用嵌套結構,即不建議將函數定義內包含另一個函數的定義,但可以分開定義再行組合;此外,函數定義內不能包含分號,因為分號會被視為函數結尾。 |
f:x↦x^2;,f(5) |
|||
ele |
1 | 取得特定代數空間(如四元數)的第n個單位元,如ele(2)即e₂=j |
ele(2) |
|||
微積分 | ||||||
limit |
3 | 計算一函數在x=x₀的極限。需注意此運算為估計,運算精度約僅有7位有效數字。第一參數為x₀;第二參數為逼近方向,1表示右極限、-1表示左極限、0表示一般的極限,此時若極限不存在則返回nan;第三參數為欲求極限的函數。 |
limit(0,1,:x↦div(x,x);) |
|||
diff |
2 | 計算一函數在x=x₀的導數。需注意此運算為估計,運算精度約僅有7位有效數字。第一參數為欲求導數x=x₀的函數;第二參數為x₀。 |
diff(cos,div(2⋅pi,3)) |
|||
integral |
4 | 計算一函數在從a到b的定積分。需注意此運算為估計,運算精度約僅有7位有效數字,且積分範圍(a和b的距離)越大,精確度會越低。第一參數為a、第一參數為b、第三參數為欲求定積分的函數、第四參數為取樣數,若未填寫則使用預設值2000。 |
integral(0,π,:x↦sin(x);) |
|||
複變 | ||||||
re |
1 | 取得一數的實數部分。 |
re(7+3i) |
7 |
||
im |
1 | 取得一數的虛數部分 |
im(7+3i) |
3 |
||
nonRealPart |
1 | 取得一數的非實數部分 |
nonRealPart(7+3i+2j+k) |
|||
scalarPartQuaternion |
1 | 取得四元數的純量部分 |
scalarPartQuaternion(7+3i+2j+k) |
|||
vectorPartQuaternion |
1 | 取得四元數的向量部分 |
vectorPartQuaternion(7+3i+2j+k) |
|||
arg |
1 | 計算一複數的輻角 |
arg(3+7i) |
1.1659045405098 |
||
cis |
1 | 計算一數的純虛指數函數值 |
cis(π) |
-1 |
||
conjugate |
1 | conjugate(7+3i) |
7-3i |
|||
統計 | ||||||
average |
不定 | 計算數組的算術平均數。 |
average(7,3,2,1) |
3.25 |
||
geoaverage |
不定 | 計算數組的幾何平均數 |
geoaverage(7,3,2,1) |
2.5457298950218 |
||
maximum |
不定 | 計算數組的最大值 |
maximum(7,3,2,1) |
7 |
||
minimum |
不定 | 計算數組的最小值 |
minimum(7,3,2,1) |
1 |
||
selectlist |
不定 | 輸出數組中指定位置的元素。第一參數為要輸出的元素序號,第二參數之後為數組 |
selectlist(2,7,3,2,1) |
3 |
||
σ |
不定 | 計算數組的標準差 |
σ(7,3,2,1) |
2.2776083947861 |
||
技術性 | ||||||
hide |
隱藏運算式
|
不定 | 在math模式下隱藏指定運算式。本函數的結果為最後一個參數。可作為連續運算式的表達,所有已輸入的運算式皆會計算,但結果會隱藏。亦可用於自訂函數中的多運算式表達。 |
hide(y←5,x←7,x⋅y),5 |
||
exprs |
一系列運算式
|
不定 | 在math模式時顯示所有運算式,運算結果為最後一則運算式。可作為連續運算式的表達,所有已輸入的運算式皆會計算。 |
exprs(y←5,x←7,x⋅y),5 |
||
lastexpr |
最後一則運算式
|
不定 | 在math模式時顯示最後一則運算式,運算結果也為最後一則運算式。可作為連續運算式的表達,所有已輸入的運算式皆會計算。 |
lastexpr(y←5,x←7,x⋅y),5 |
||
equalexpr |
連續等式
|
不定 | 生成連續等式。 |
equalexpr(2+2,2*2) |
4 |
|
call |
呼叫函數
|
不定 | 呼叫一個函數。用於處理匿名函數或返回值是函數的情況。 |
call((:x,y↦sin(x)+cos(y);),π,0) |
||
<functionName>AtModule<ModulePageName> |
不定 | 调用其他模块的函数。須注意函數名稱必須是純英文、模組名稱也必須是純英文,不能有空格或其他符號。例如若需要呼叫Module:Element中的 getAtomicWeight 函數,則須表示為getAtomicWeightAtModuleElement 。 |
getAtomicWeightAtModuleElement(10) |
|||
range |
指定範圍
|
3 | 指定一範圍,當一數落在該範圍外則視為非數(NaN)。第一參數為要判定的數,第二和第三參數分別為範圍的最小和最大值。 |
range(7,1,5),range(4,1,5) |
, |
|
if |
3 | 指定特定條件下時的運算式。第一參數為條件、第二參數為條件為真時的運算式、第三參數為條件為假時的運算式。 |
if(3>2,1,0) |
0 |
||
iff |
函數型條件運算式
|
3 | 同if,不過參數可以是函數,條件成立時才會呼叫。 |
iff(3>2,:nil↦1;,:nil↦2;) |
||
ifelse |
條件運算式 if...else
|
不定 | 類似if,用法為ifelse(條件1, 條件1為真的結果, 條件2, 條件2為真的結果, ... , 條件n, 條件n為真的結果, 條件皆為假的結果) |
ifelse(3>2,10,3<2,20,30) |
0 |
|
ifelsef |
函數型條件運算式 if...else
|
不定 | 同ifelse,不過參數可以是函數,條件成立時才會呼叫。 |
ifelsef(3>2,:nil↦10;,3<2,:nil↦20;,:nil↦30;) |
||
random |
2 | 取一個隨機數。若無指定參數,或參數中包含非數(NaN),則取0-1之間的隨機實數;若指定了參數1,則取1到參數1之間的隨機數;若指定了參數1與參數2,則取參數1到參數2之間的隨機數 |
random(1,10) |
3 |
||
randomseed |
設定隨機種子碼
|
1 | 將隨機數的種子碼設定為輸入的參數,並返回實際設定的種子碼。若輸入的參數非實數則用當前時間隨機產生種子碼。 |
randomseed(10) |
10 |
|
三角函数 | ||||||
sin |
1 | 計算一數的正弦值 |
sin(π) |
0 |
||
cos |
1 | 計算一數的餘弦值 |
cos(π) |
-1 |
||
tan |
1 | 計算一數的正切值 |
tan(π) |
0 |
||
cot |
1 | 計算一數的餘切值 |
cot(div(π,2)) |
-8.1656196765977e+15 |
||
sec |
1 | 計算一數的正割值 |
sec(π) |
-1 |
||
csc |
1 | 計算一數的餘割值 |
csc(div(π,2)) |
8.1656196765977e+15 |
||
asin |
1 | 計算一數的反正弦值 |
asin(1) |
1.5707963267949 |
||
acos |
1 | 計算一數的反餘弦值 |
acos(1) |
0 |
||
atan |
1 | 計算一數的反正切值 |
atan(1) |
0.78539816339745 |
||
acot |
1 | 計算一數的反餘切值 |
acot(1) |
0.78539816339745 |
||
asec |
1 | 計算一數的反正割值 |
asec(1) |
0 |
||
acsc |
1 | 計算一數的反餘割值 |
acsc(1) |
1.5707963267949 |
||
sinh |
1 | 計算一數的雙曲正弦值 |
sinh(π) |
11.548739357258 |
||
cosh |
1 | 計算一數的雙曲餘弦值 |
cosh(π) |
11.591953275522 |
||
tanh |
1 | 計算一數的雙曲正切值 |
tanh(π) |
0.99627207622075 |
||
coth |
1 | 計算一數的雙曲餘切值 |
coth(π) |
1.0037418731973 |
||
sech |
1 | 計算一數的雙曲正割值 |
sech(π) |
0.086266738334054 |
||
csch |
1 | 計算一數的雙曲餘割值 |
csch(π) |
0.086589537530047 |
||
asinh |
1 | 計算一數的雙曲反正弦值 |
asinh(1) |
0.88137358701954 |
||
acosh |
1 | 計算一數的雙曲反餘弦值 |
acosh(1) |
0 |
||
atanh |
1 | 計算一數的雙曲反正切值 |
atanh(0.5) |
0.54930614433405 |
||
acoth |
1 | 計算一數的雙曲反餘切值 |
acoth(1.5) |
0.80471895621705 |
||
asech |
1 | 計算一數的雙曲反正割值 |
asech(1) |
0 |
||
acsch |
1 | 計算一數的雙曲反餘割值 |
acsch(1) |
0.88137358701954 |
||
cis |
1 | 計算一數的純虛指數函數值 |
cis(π) |
-1 |
||
gd |
1 | 計算一數的古德曼函數值 |
gd(e) |
1.4390113159637 |
||
arcgd |
1 | 計算一數的反古德曼函數值 |
arcgd(1) |
1.2261911708835 |
||
cogd |
1 | 計算一數的餘古德曼函數值 |
cogd(π) |
0.08648169656714 |
local p = {}
function p.calculate(frame)
local args
local can_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 = frame.args
local yesno = require('Module:Yesno')
can_math = yesno(args['use math'] or args['use_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
local body = p.calc( args[1] or args['1'] or '', ( {
cmath = require("Module:Complex Number").cmath.init(),
} ) [ args['class'] ] , (( {
cmath = require("Module:Complex Number").cmath.init(),
} ) [ args['class'] ] ).toComplexNumber )
if can_math then body = frame:callParserFunction{name = "#tag:math", args = {body}} end
return body
end
function p.toPostfix(frame)
local args
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 = frame.args
else
-- We're being called from another module or from the debug console, so assume
-- the args are passed in directly.
args = frame
end
local format = args['format'] or "{{{1}}} ";
format = mw.ustring.gsub(format, "%{%{%{.-%}%}%}", "%%s" );
local it = mw.ustring.find(format, "%%s", 1)
format = mw.ustring.gsub(format, "\\n", "\n")
local result, body = p.infixToPostfix( args[1] or args['1'] or '' ), ''
for i, result_str in pairs( result ) do
body = body .. mw.ustring.gsub(format, "%%s", tostring(result_str.name))
end
return body
end
function numberToAZ(num)
local body = ''
local s = tostring(math.floor(tonumber(num)))
for i = 1, #s do
body = body .. mw.ustring.char(tonumber(s:sub(i, i)) + 65)
end
return body
end
function stringToTable(s) --字串轉陣列
local t, i = {}, 1
while i <= #s do
if s:sub(i, i) ~= ' ' then
local j, k = mw.ustring.find(s,"[%d%a]+",i)
if (j or (i+1)) > i then
t[#t + 1] = s:sub(i, i)
else
t[#t + 1] = s:sub(j, k)
i = k
end
end
i = i + 1
end
return t
end
--mw.log(p.calc("45*5+(1+5-9+((12-5)+5i+(9)/4)*sqrt(-6))*-8",require("Module:Complex Number").cmath.init(),require("Module:Complex Number").cmath.init().toComplexNumber,true))
-- 346.97959 - 181.262241 i
--mw.log(p.calc("45*5+(1+5-9+((12-5)+5+(9)/4)*sin(-6))*-8",nil,nil,true))
-- 217.146633205
--mw.log(p.calc("(i*j*k)",p.qmath.init(),p.qmath.init().toQuaternionNumber,true))
-- (-1)
function p.calc(input_str, math_lib, number_Constructer, debug_flag)
local mathlib, numberConstructer = math_lib or math, number_Constructer or tonumber
local postfix = p.infixToPostfix(input_str, debug_flag)
local call_stack = {}
local calc_stack = {}
local dbg_func = mw.log
if debug_flag ~= true then dbg_func = function()end end
for i = 1,#postfix do
local it = postfix[i]
if it.propetry == "operator" then
local opdata = p.symbol_table[it.name]
xpcall(function()
if it.name == ',' then
if calc_stack[#calc_stack-1] ~= ',' then call_stack[#call_stack + 1] = calc_stack[#calc_stack-1] end
if calc_stack[#calc_stack] ~= ',' then call_stack[#call_stack + 1] = calc_stack[#calc_stack] end
calc_stack[#calc_stack] = nil; calc_stack[#calc_stack] = ','
elseif opdata.count == 1 then
calc_stack[#calc_stack] = opdata.calc(calc_stack[#calc_stack],mathlib,numberConstructer)
else
calc_stack[#calc_stack - 1] = opdata.calc(calc_stack[#calc_stack - 1]or 0 ,calc_stack[#calc_stack]or 0,mathlib,numberConstructer)
calc_stack[#calc_stack] = nil
end
end, function(message)
error("計算失敗:套用運算子 \"" .. mw.text.trim(it.name) .. "\" 發生錯誤 \"" .. message .. "\" .")
end)
xpcall(function() (calc_stack[#calc_stack]):clean() end,function(_)end)
dbg_func(it.name, '\t', print_sk(calc_stack,', ') )
elseif it.propetry == "func" then
local calfunc, functype = mathlib[it.name], type(tonumber)
if type(calfunc) ~= functype and type(_G[it.name]) == functype then calfunc = _G[it.name] end
if type(calfunc) == functype then
xpcall(function()
if #call_stack > 0 then
calc_stack[#calc_stack] = calfunc( unpack( call_stack ) )
else
calc_stack[#calc_stack] = calfunc( calc_stack[#calc_stack] )
end
end, function(message)
error("計算失敗:執行函數 \"" .. it.name .. "\" 發生錯誤 \"" .. message .. "\" .")
end)
else
error("計算失敗:無法執行函數 \"" .. it.name .. "\" ")
end
xpcall(function() (calc_stack[#calc_stack]):clean() end,function(_)end)
dbg_func(it.name, '\t', print_sk(calc_stack,', ') )
else
local get_data = numberConstructer(it.name)
if get_data == nil then get_data = numberConstructer(_G[it.name]) or numberConstructer(mathlib[it.name]) or numberConstructer(it.name) end
if get_data == nil then error("計算失敗:未知的變數 \"" .. it.name .. "\" ") end
calc_stack[#calc_stack + 1] = get_data
xpcall(function() (calc_stack[#calc_stack]):clean() end,function(_)end)
dbg_func(it.name, '\t', print_sk(calc_stack,', ') )
end
end
if #calc_stack == 1 then return calc_stack[#calc_stack] end
return numberConstructer(0)
end
p.symbol_table = {
['+'] = { propetry="op", multp = true, count = 2, priority=2, calc=function(a,b,c,d)return d(a)+d(b) end},
["+ "] = { propetry="op", count = 1, priority=5, calc=function(a,c,d)return d(a) end},
['-'] = { propetry="op", multp = true, count = 2, priority=2, calc=function(a,b,c,d)return d(a)-d(b) end},
["- "] = { propetry="op", count = 1, priority=5, calc=function(a,c,d)return -d(a) end},
['*'] = { propetry="op", multp = true, count = 2, priority=3, calc=function(a,b,c,d)return d(a)*d(b) end},
["* "] = { propetry="op", count = 1, priority=5 , calc=function(a,c,d) if type(c.conjugate)==type(function()end) then return c.conjugate(d(a))else return d(a)end end},
['/'] = { propetry="op", count = 2, priority=3, calc=function(a,b,c,d)return d(a)/d(b) end},
['%'] = { propetry="op", count = 2, priority=3, calc=function(a,b,c,d)return d(a)%d(b) end},
['^'] = { propetry="op", count = 2, priority=4, calc=function(a,b,c,d)return c.pow(d(a),d(b)) end},
[','] = { propetry="op", count = 2, priority=1 },
}
function print_sk(sk,sp)
local body = ''
for i = 1,#sk do
if body ~= '' then body = body .. (sp or ' ') end
if type(sk[i]) == type({}) and sk[i].name then if sk[i].name == "$END" then body = body .. '$' else body = body .. sk[i].name end
else body = body .. tostring(sk[i]) end
end
return body
end
function p.infixToPostfix(input_str, debug_flag)
local str, index, num_list = input_str, 0, {};
local dbg_func = mw.log
if debug_flag ~= true then dbg_func = function()end end
str = mw.ustring.gsub(str,"([A-Za-hj-z])i","%1I")
str = mw.ustring.gsub(str,"([A-Za-ik-z])j","%1J")
str = mw.ustring.gsub(str,"([A-Za-jl-z])k","%1K")
str = mw.ustring.gsub(str,"i([A-Za-hj-z])","I%1")
str = mw.ustring.gsub(str,"j([A-Za-ik-z])","J%1")
str = mw.ustring.gsub(str,"k([A-Za-jl-z])","K%1")
local result = mw.ustring.gsub(str,"%d*%.?%d*%s*[ijk]?",
function(b)
if b ~= nil and mw.text.trim(b) ~= '' then
index = index + 1
num_list[#num_list + 1] = b
return tostring(index)
end
return ''
end
);
result = mw.ustring.gsub(result,"I","i")
result = mw.ustring.gsub(result,"J","j")
result = mw.ustring.gsub(result,"K","k")
--------------------------------------------------------
local str2, index, azid, func_list = result, 0, '', {};
local result = mw.ustring.gsub(str2,"%a[%a%d]*%s*%(?",
function(b)
if b ~= nil and mw.text.trim(b) ~= '' then
if mw.ustring.find(b,"%(") then
local func_name = mw.ustring.match(b,"%a[%a%d]*")
if func_name ~= nil and mw.text.trim(func_name) ~= '' then
index, azid = index + 1, numberToAZ(index)
func_list[azid] = func_name
return ' ' .. azid .. ' '
end
else
num_list[#num_list + 1] = b
return tostring(#num_list)
end
end
return ''
end
);
for i=1,#num_list do num_list[i] = mw.ustring.gsub(num_list[i],"%s+",'') end
local mid_expr = stringToTable(result)
mid_expr[#mid_expr + 1] = "$END"
local stack, postfix = {{name="$END",elements=0}}, {}
for i = 1,#mid_expr do
local it = mid_expr[i]
if it == "$END" then
while #stack > 0 and stack[#stack].name ~= "$END" do
if stack[#stack].elements < p.symbol_table[stack[#stack].name].count then
dbg_func("==operator ",stack[#stack].name, " need ",p.symbol_table[stack[#stack].name].count, " elements, but got ",stack[#stack].elements)
return {}
end
postfix[#postfix + 1] = {name=stack[#stack].name, propetry=stack[#stack].propetry}
stack[#stack] = nil --pop
stack[#stack].elements = (stack[#stack].elements or 0) + 1
end
dbg_func("結束",'\t', print_sk(postfix,' ') ,'\t',print_sk(stack))
elseif mw.ustring.match(it,"[%a%(]") then
stack[#stack + 1] = {name=it,elements=0,propetry='func'}
dbg_func(it, "括號開始",'\t', print_sk(postfix,' ') ,'\t',print_sk(stack))
elseif p.symbol_table[it] ~= nil and p.symbol_table[it].propetry == "op" then
local op_it = p.symbol_table[it]
local op_ls = p.symbol_table[mid_expr[i-1]]
local flag = mw.ustring.match(mid_expr[i-1] or '',"[%a%(]") if (mid_expr[i-1] or '娜娜奇') == '娜娜奇' then flag = false end
if ( op_ls or (i == 1) or flag ) and op_it.multp == true then
stack[#stack + 1] = {name=it .. ' ',elements=0,propetry='operator'}
else
while p.symbol_table[stack[#stack].name] and p.symbol_table[stack[#stack].name].priority and
p.symbol_table[stack[#stack].name].priority >= p.symbol_table[it].priority do
if stack[#stack].elements < p.symbol_table[stack[#stack].name].count then
dbg_func("==operator ",stack[#stack].name, " need ",p.symbol_table[stack[#stack].name].count, " elements, but got ",stack[#stack].elements)
return {}
end
postfix[#postfix + 1] = {name=stack[#stack].name, propetry=stack[#stack].propetry}
stack[#stack] = nil --pop
stack[#stack].elements = (stack[#stack].elements or 0) + 1
end
stack[#stack + 1] = {name=it,elements=1, propetry='operator'}
end
dbg_func(it, "運算子",'\t', print_sk(postfix,' ') ,'\t',print_sk(stack))
elseif mw.ustring.match(it,"%d+") then
postfix[#postfix + 1] = {name=num_list[tonumber(it)] or ("N" .. it), propetry="number"}
stack[#stack].elements = (stack[#stack].elements or 0) + 1
dbg_func(it, "數字",'\t', print_sk(postfix,' ') ,'\t',print_sk(stack))
elseif it == ')' then
local flag = mw.ustring.match(stack[#stack].name,"[%a%(]")
while flag == nil do --遇 ) 輸出至 (
if stack[#stack].elements < p.symbol_table[stack[#stack].name].count then
dbg_func("==operator ",stack[#stack].name, " need ",p.symbol_table[stack[#stack].name].count, " elements, but got ",stack[#stack].elements)
return {}
end
postfix[#postfix + 1] = {name=stack[#stack].name, propetry=stack[#stack].propetry}
stack[#stack] = nil --pop
stack[#stack].elements = (stack[#stack].elements or 0) + 1
flag = mw.ustring.match(stack[#stack].name,"[%a%(]")
end
if mw.ustring.match(stack[#stack].name,"%a") then
postfix[#postfix + 1] = {name=func_list[stack[#stack].name] or stack[#stack].name, propetry=stack[#stack].propetry}
end
stack[#stack] = nil --pop
stack[#stack].elements = (stack[#stack].elements or 0) + 1
dbg_func(it, "結束括號",'\t', print_sk(postfix,' ') ,'\t',print_sk(stack))
end
end
return postfix
end
return p