Lua學習筆記

安裝Lua最小開發運行環境:
apt-get install lua5.1-0-dev
find / -name lua.h
/home/hanxiaohua/work1/MathTool/lua/lua.h
/usr/include/lua5.1/lua.h
./luatest
./luatest: /usr/lib/x86_64-linux-gnu/liblua5.1.so.0: no version information available (required by ./luatest)
root@ubuntu:/home/cpptest/lua# ./luatest NumberTheory.lua
5!=120
6!=720
7!=5040
8!=40320
9!=362880
10!=3628800
11!=39916800
12!=479001600
4    -4    -4
4    6
totient(37)=36
totient(57)=36
totient(63)=36
totient(74)=36
totient(76)=36
100
7
PowerMod(5,-2,17)=15
PowerMod(5,-1,17)=7
PowerMod(5,0,17)=1
PowerMod(5,1,17)=5
PowerMod(5,2,17)=8
PowerMod(5,4,17)=13
PowerMod(5,8,17)=16
PowerMod(5,16,17)=1
在前30個正整數中,1,8,12,15,16,20,21,24,28,30,沒有原根
lprimroot(2)=1,lprimroot(3)=2,lprimroot(4)=3,lprimroot(5)=2,lprimroot(6)=5,lprimroot(7)=3,lprimroot(9)=2,lprimroot(10)=3,lprimroot(11)=2,lprimroot(13)=2,lprimroot(14)=3,lprimroot(17)=3,lprimroot(18)=5,lprimroot(19)=2,lprimroot(22)=7,lprimroot(23)=5,lprimroot(25)=2,lprimroot(26)=7,lprimroot(27)=2,lprimroot(29)=2,有原根

function Factorial(n)
    if n==0 or n==1 then
        return 1
    else
        return n * Factorial(n-1)
    end
end

--print("Enter a number : ")
--i = io.read("*number")   
for i=5,12,1 do     
    io.write(i,"!=",Factorial(i),"\n")
end

--求2個整數的最大公約數
function GcdInt(a,b)
    if(a*b<0) then
        return -GcdInt(math.abs(a),math.abs(b))
    end
    if(a<b) then
        local temp=a
        a=b
        b=temp
    end
    if(a%b==0)then
        return b
    else
        return GcdInt(a%b,b)
    end
end

local ret=GcdInt(12,32)
local ret1=GcdInt(-12,32)
local ret2=GcdInt(12,-32)
print(ret,ret1,ret2)

function Iscoprime(a,b)
    local ret=0
    if(GcdInt(a,b)==1)then
        ret=1
    end
    return ret
end

--φ(n)表示不大於n且與n互素的正整數個數、n階循環羣中n階元的個數、本原n次單位根(n次單位原根)的個數、整數模n乘法羣(模n既約剩餘類)(Z/p^nZ)^×中與n互素剩餘類的個數
function Phi(n)
    local ret=0
    if(n==1)then
        return 1
    end
    for i=1,n-1,1 do     
        ret=ret+Iscoprime(n,i)
    end    
    return ret
end

--T(n)表示n的正因子的個數、n階循環羣子羣的個數、Z/nZ理想的個數
function Sigma0(n)
    local ret=0
    for d=1,n,1 do 
        if(n%d==0)then
            ret=ret+1
        end
    end
    return ret
end

--totient(12)=4
--|S(C_12)|=T(12)=|{1,2,3,4,6,12}|=6
print(Phi(12),Sigma0(12))

local v36={37,57,63,74,76}
for i,v in pairs(v36) do
    io.write("totient(",v,")=",Phi(v),"\n")
end    

function Mod(ret,n)
    if(ret<0)then
        local ret1=ret+(-ret+1)*n
        return ret1%n
    end
    return ret%n
end

function mod(ret,n)
    local raw_mod=ret%n
    if (raw_mod==0) then
        return 0
    elseif (ret>= 0) then
        return raw_mod
    else
        return raw_mod+n
    end
end

function inverse_mod_p(u,p)
    for i=1,p-1,1 do 
        if (Mod(u * i, p ) == 1)then
            return i
        end        
    end
    return nil
--[[
    local t1 = 0
    local t3 = 0
    local q  = 0
    local u1 = 1
    local u3 = u
    local v1 = 0
    local v3 = p
    local inv_v = 0
    
    while( v3 ~= 0)    do
        q = u3 / v3
        t1 = u1 - v1 * q
        t3 = u3 - v3 * q
        u1 = v1
        u3 = v3
        v1 = t1
        v3 = t3
    end    
    inv_v=mod(u1,p)
    if (mod(u * inv_v, p ) ~= 1)then
        return 0
    end
    return inv_v
]]--
end

function PowerMod(a,k,p)
    if k<0 then
        local a1=inverse_mod_p(a,p)
        return PowerMod(a1,-k,p)
    end
    local ans=1
    for i=1,k,1 do 
        ans=ans*a%p
    end
    return ans
end

function OrderMod(a,p)
    local k=1
    while(k<=p)    do
        if(PowerMod(a,k,p)==1)then
         break
        end
        k=k+1
    end
    return k
end

function LogMod(b,a,p)
    local k=1
    while(k<=p)    do
        if(PowerMod(a,k,p)==b)then
         break
        end
        k=k+1
    end
    return k
end

print(LogMod(57, 3, 113))
print(inverse_mod_p(5,17))
local bArr={-2,-1,0,1,2,4,8,16}
for i,v in pairs(bArr) do
    io.write("PowerMod(5,",v,",17)=",PowerMod(5,v,17),"\n")
end    

function is_primitive_root(a,p)
    local k=OrderMod(a,p)
    return k==Phi(p)
end

--計算模n的最小原根
function PrimitiveRootMod(n)
    for a=1,n-1,1 do
        local ret=is_primitive_root(a,n)
        if(ret)then
            return a
        end
    end
    return nil
end

io.write("在前30個正整數中,")
for n=1,30,1 do 
    if PrimitiveRootMod(n)==nil then 
        io.write(n,",")
    end
end
io.write("沒有原根\n")
for n=1,30,1 do 
    local ret=PrimitiveRootMod(n)
    if ret~=nil then 
        io.write("lprimroot(",n,")=",ret,",")
    end
end
io.write("有原根\n")

test.lua中依賴於宿主程序calllua的Lua代碼:暫無
root@ubuntu:/home/cpptest/lua# g++ -o calllua calllua.cpp -I /usr/include/lua5.1/ -llua5.1
Hello, World!
10+30=40
1    靈智系
2    蠻荒系
3    地脈系
4    天羽系
5    蜚廉系
6    瑞獸系
7    神巫系
8    幽冥系
PHYLE_MAX=8
eWorldPhyle.P_TERRAN=0
eWorldPhyle.PHYLE_MAX=8
0    靈智系
1    蠻荒系
2    地脈系
3    天羽系
4    蜚廉系
5    瑞獸系
6    神巫系
7    幽冥系
(1/17)=1,x=1
(2/17)=1,x=6
(3/17)=-1,x=0
(4/17)=1,x=2
(5/17)=-1,x=0
(6/17)=-1,x=0
(7/17)=-1,x=0
(8/17)=1,x=5
(9/17)=1,x=3
(10/17)=-1,x=0
(11/17)=-1,x=0
(12/17)=-1,x=0
(13/17)=1,x=8
(14/17)=-1,x=0
(15/17)=1,x=7
(16/17)=1,x=4
(17/17)=0,x=0
3    8    8    1
1二次剩餘:[1,2,4,8,9,13,15,16,]
-1二次非剩餘:[3,5,6,7,10,11,12,14,]
0整除:[17,]
10+5=15

-- test.lua
print "Hello, World!"

myName = "beauty girl"  
helloTable = {name = "mutou", IQ = 125}  
  
function helloAdd(num1, num2)  
    return (num1 + num2)  
end;  

sum=helloAdd(10,30)
print("10+30="..sum)

gszWorldPhyle= {"靈智系", "蠻荒系", "地脈系", "天羽系", "蜚廉系", "瑞獸系", "神巫系", "幽冥系"}
--i 表示索引, v 表示值
for i,v in ipairs(gszWorldPhyle) do
   print(i, v)
end
PHYLE_MAX=#gszWorldPhyle
print("PHYLE_MAX="..PHYLE_MAX)

-- 填index=-1從0開始,填index=0或不填index從1開始,……
function CreateEnumTable(tbl, index) 
    local enumtbl = {} 
    local enumindex = index or 0 
    for i, v in ipairs(tbl) do 
        enumtbl[v] = enumindex + i 
    end 
    return enumtbl 
end
--[[
    種族= 0人型系,1野獸系,2植物系,3飛行系,4昆蟲系,5龍系,6神系,7不死系
]]--
eWorldPhyle = CreateEnumTable({"P_TERRAN", "P_BEAST", "P_PLANTS", "P_FLY", "P_INSECT", "P_DRAGON", "P_PROTOSS", "P_UNDEAD", "PHYLE_MAX"},-1)
print("eWorldPhyle.P_TERRAN="..eWorldPhyle.P_TERRAN)
print("eWorldPhyle.PHYLE_MAX="..eWorldPhyle.PHYLE_MAX)

function getWorldPhyle(Phyle) 
    return gszWorldPhyle[Phyle+1]
end

for i=eWorldPhyle.P_TERRAN,eWorldPhyle.PHYLE_MAX-1,1 do
    local v=getWorldPhyle(i)
    print(i,v)
end

--正確的獲取table的長度應該是遍歷,而且要用pairs,不要用ipairs
local function get_len(tb)
  local len = 0
  for k,v in pairs(tb) do
    len= len+1
  end
return len
end

--[[
按定義計算二次剩餘和二次非剩餘
x=8,(13/17)=1
x=無解,(5/17)=-1
]]--
function Legendre(a,p)
    local x=0
    if(a%p==0) then
        return 0,x--是p的倍數
    end
    for i=1,p-1,1 do
       if((i*i-a)%p==0) then
              x=i
           return 1,x--a是p的二次剩餘
       end
    end
    return -1,x--a是p的二次非剩餘
end

local Ret17={[1]={}, [-1]={}, [0]={}}
for i=1,17,1 do
local ret,x=Legendre(i,17)
local str = string.format("(%d/17)=%d,x=%d",i,ret,x)
print(str)
--print(i,ret,x)
table.insert(Ret17[ret],i)
end
print(get_len(Ret17),#Ret17[1], #Ret17[-1], #Ret17[0])

function getRetStr(ret) 
    local strArr={"二次非剩餘","整除","二次剩餘"}
    return strArr[ret+2]
end

for k,v in pairs(Ret17) do
    io.write(k..getRetStr(k)..":[")
    for k1,v1 in pairs(v) do
        io.write(v1,",")
    end
    print("]")
end

lua中元表的應用例子1:lua複數類
root@ubuntu:/home/cpptest/lua# ./luatest2
./luatest2: /usr/lib/x86_64-linux-gnu/liblua5.1.so.0: no version information available (required by ./luatest2)
4    5
-2    -3
-1    7
0.28    -0.04
c:4    5
The sum is 21
luapythagorean(3,4)=5.000000

-- test2.lua

function add(x,y)
    return x+y
end

function pythagorean(a,b) 
local c2 = a^2 + b^2 
return math.sqrt(c2) 
end

function fun(x)
    return math.sqrt(math.sqrt(4*x*x+1)-x*x-1)
end

complex={
__add=function(op1,op2)
             op = {}
             op.x = op1.x + op2.x
             op.y = op1.y + op2.y
             setmetatable(op,complex)
             return op
           end,

__sub=function(op1,op2)
 op = {}
 op.x = op1.x - op2.x
 op.y = op1.y - op2.y
 setmetatable(op,complex)
 return op
end,

__mul=function(op1,op2)
 op = {}
 op.x = op1.x * op2.x-op1.y * op2.y
 op.y = op1.x* op2.y + op2.x* op1.y
 setmetatable(op,complex)
 return op
end,

__div=function(op1,op2)
 op = {}
 op.x = (op1.x * op2.x+op1.y * op2.y)/(op2.x * op2.x+op2.y * op2.y)
 op.y = (-op1.x* op2.y + op2.x* op1.y)/(op2.x * op2.x+op2.y * op2.y)
 setmetatable(op,complex)
 return op
end,

create=function(o)
 o = o or {}
 setmetatable(o,complex)
 return o
end             
}
    
a=complex.create{x=1,y=1}
b=complex.create{x=3,y=4}
c = a + b
print(c.x, c.y)  -- 輸出 4,5
d = a - b
print(d.x, d.y)  -- 輸出 -2,-3
e = a * b
print(e.x, e.y)  -- 輸出 -1,7
f = a / b
print(f.x, f.y)  -- 輸出 0.28,-0.04

meta={
__add=function(op1,op2)
             op = {}
             op.x = op1.x + op2.x
             op.y = op1.y + op2.y
             return op
end
    }
    
a={x=1,y=1}
setmetatable(a,meta)
b={x=3,y=4}
c = a + b
print("c:"..c.x, c.y) -- 輸出 4,5

大家可以參考lua手冊,metatable是被譯作元表,Lua 中的每個值都可以用一個 metatable。這個 metatable 就是一個原始的 Lua table ,它用來定義原始值在特定操作下的行爲。
一個 metatable 可以控制一個對象做數學運算操作、比較操作、連接操作、取長度操作、取下標操作時的行爲,metatable 中還可以定義一個函數,讓 userdata 作垃圾收集時調用它。對於這些操作,Lua 都將其關聯上一個被稱作事件的指定健。當 Lua 需要對一個值發起這些操作中的一個時,它會去檢查值中 metatable 中是否有對應事件。如果有的話,鍵名對應的值(元方法)將控制 Lua 怎樣做這個操作。 
metatable通過其包含的函數來給所掛接的table定義一些特殊的操作,包括:
__add: 定義所掛接table的加法操作
__mul: 定義乘法操作
__div: 定義除法操作
__sub: 定義減法操作
__unm: 定義負操作, 即: -table的含義
__tostring: 定義當table作爲tostring()函式之參數被呼叫時的行爲(例如: print(table)時將呼叫tostring(table)作爲輸出結果)
__concat: 定義連接操作(".."運算符)
__index: 定義當table中不存在的key值被試圖獲取時的行爲
__newindex: 定義在table中產生新key值時的行爲
Lua中用表類型模擬複數,x表示實部,y表示虛部;然後把複數相加的邏輯(實部+實部,虛部+虛部)寫進元表內 __add 方法中,因此,(1+1i) + (3+4i) = (4+5i)。元表是普通表變量中的一張隱藏的表,用 setmetatable 函數設置它,想要讀出來則用 getmetatable。
如果我們正在編制一個複數計算程序,需要定義許多複數,那麼能實現一個“永久”的複數類型 (complex)那是再好不過了。在該代碼中,利用 complex.create 創建複數,只需要輸入複數的實部和虛部的值即可,然後可以對複數使用加法運算,加法運算的結果(這裏指 c)也是複數。我們這裏說一個表是複數(表),不僅僅要求該表具有 x,y 兩項數值,而且要具有複數的行爲,類似“相加”、“相減”、“相乘”。。。等等。

Lua基礎知識
常量
變量
a=10
a=2.5
a="諸葛量化"
=是賦值符號,==是等於符號
lua變量必須以字母或者下劃線開頭,區分大小寫
lua的關鍵字不能用作變量名
8種數據類型:
nil、boolean、number、string、function、userdata、thread、table
局部變量由關鍵字local定義的,全局變量沒有被local定義
Lua語言優勢:
小巧、快速、易於嵌入到C語言、與C語言交互方便、易於在線更新
lua、luac一個是運行環境,一個是編譯器
Lua語言調用C語言帶參數的方法:getString
luaL_checkstring(L,1);//獲取傳進來的參數,檢查第1個參數
lua_pushstring(L,buf);壓入棧中
return 1;//指明返回值有1個
Lua語言和C語言的交互機制
lua語言的索引是從1開始的
從上到下是-1、-2、-3……
從下到上是1、2、3、……
數組語言不僅僅是C語言
Lua語言不依賴於數組語言的數據類型

C語言調用Lua語言的方法
Lua語言沒有入口方法
執行Lua中的main方法(無參數、無返回值)
lua_getglobal(L,"main");//Lua棧的第一個位置放進方法
lua_call(L,0,0);//第二個表示傳進參數的個數,第三個表示返回值的個數
方法調用結束後會自動把棧清空
使用C語言執行一個Lua文件
luaL_newstate創建一個lua_State
Lua_openlibs加載庫(print是庫裏面的方法)
dofile(L,"app.lua")
使用C語言執行一段字符串Lua腳本
dostring(L,"print(\"Hello eoe\")","MyScript");
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章