2008年12月25日 星期四

學校夜景


從我的手機上找到的相片。這是夏天颱風前夕到學校時照的。我很少照相,也許不是照得很好,而且手機照起來有過度曝光的問題。不過過度曝光出來的照片有竟有另外的感覺。
在藍天中有三個亮點,那不是UFO。長型的是月亮,另外二個好像是金星及火星,在手機照起來都變得怪怪的。
這算是我照得相片中,少數算是有點樣子的。

2008年12月23日 星期二

Lua圖像迷宮


修改成長時轉向的生成機率,讓它和現在位置有關,就可以產生這樣的迷宮圖。

不平衡成長迷宮


加入調整成長的機率,好像會走比較長

找迷宮解程式修改

-- reslove maze
--]]
path={};
search_count = 1;
search_pos={x=start_pos.x, y=start_pos.y, dir=0};
table.insert(path,search_pos);
function read_north()
    if( search_pos.y == 1 ) then return end;
    if( maze[search_pos.x][search_pos.y-1].s == true ) then
        return;
    else
        if ( maze[search_pos.x][search_pos.y-1].v == true ) then
            maze[search_pos.x][search_pos.y-1].v = false;
            local node = {x=search_pos.x, y=search_pos.y-1, dir=3, r=search_count};
            table.insert(path,node);
        end
    end
end
function read_south()
    if( search_pos.y == size.y ) then return end;
    if( maze[search_pos.x][search_pos.y].s == true ) then
        return;
    else
        if ( maze[search_pos.x][search_pos.y+1].v == true ) then
            maze[search_pos.x][search_pos.y+1].v = false;
            local node = {x=search_pos.x, y=search_pos.y+1, dir=1, r=search_count};
            table.insert(path,node);
        end
    end
end
function read_east()
    if( search_pos.x == size.x ) then return end;
    if( maze[search_pos.x][search_pos.y].e == true ) then
        return;
    else
        if ( maze[search_pos.x+1][search_pos.y].v == true ) then
            maze[search_pos.x+1][search_pos.y].v = false;
            local node = {x=search_pos.x+1, y=search_pos.y, dir=4, r=search_count};
            table.insert(path,node);
        end
    end
end
function read_west()
    if( search_pos.x == 1 ) then return end;
    if( maze[search_pos.x-1][search_pos.y].e == true ) then
        return;
    else
        if ( maze[search_pos.x-1][search_pos.y].v == true ) then
            maze[search_pos.x-1][search_pos.y].v = false;
            local node = {x=search_pos.x-1, y=search_pos.y, dir=2, r=search_count};
            table.insert(path,node);
        end
    end
end
while ( not (search_pos.x == target_pos.x and search_pos.y == target_pos.y) ) do
    read_north();
    read_south();
    read_east();
    read_west();
    search_count = search_count + 1;
    search_pos.x = path[search_count].x;
    search_pos.y = path[search_count].y;
    search_pos.dir = path[search_count].dir;
--    print(search_count, search_pos.x, search_pos.y, path[search_count].r );
end
修改為使用訪問過的座標標記的方式。這樣可以解有廻路的迷宮。

2008年12月22日 星期一

Lua程式開發心得:迷宮程式撰寫

迷宮程式在寫的時候,不用考量資料要多少欄位,就想到時再加上去,所以使用Lua開發時資料結構都不用擔心。
再加上Lua for Windows有許多可用的模組,在使用Windows也不用想太多和資源取用的問題。
所以程式可以在沒有規劃下180行就做出來了。
用其他靜態語言,又要改宣告,或改回傳值。光是對資料型別就花了不少時間,一下子就把想法給遺忘了。
Lua真是不錯用。


2008年12月21日 星期日

GD:迷宮產生器及解


require "gd"
grid={x=10,y=10};
size={x=50,y=50};
start_pos={x=1,y=1};
target_pos={x=50,y=50};
maze={};
for u=1,size.x,1 do
    maze[ u]={};
    for v=1,size.y,1 do
        maze[ u][v]={v=false,s=true,e=true};
    end
end
math.randomseed(os.time());
total_count = size.x*size.y;
magic= math.random(1,total_count);
cur_pos={};
function magic_to_pos()
    local x,y;
    magic = (magic + 997)% total_count;
    x = magic % size.x + 1;
    y = math.floor(magic / size.x) + 1;
    return x,y;
end
cur_pos.x , cur_pos.y = magic_to_pos();
cur_pos.dir = math.random(1,4);
maze[cur_pos.x][cur_pos.y].v = true;
cur_count = 1;
function move_north()
    if( cur_pos.y == 1 ) then return false end;
    if( maze[cur_pos.x][cur_pos.y-1].v == true ) then
        return false;
    else
        cur_pos.y = cur_pos.y - 1;
        maze[cur_pos.x][cur_pos.y].s=false;
        maze[cur_pos.x][cur_pos.y].v=true;
        return true;
    end
end
function move_south()
    if( cur_pos.y == size.y ) then return false end;
    if( maze[cur_pos.x][cur_pos.y+1].v == true ) then
        return false;
    else
        maze[cur_pos.x][cur_pos.y].s=false;
        cur_pos.y = cur_pos.y + 1;
        maze[cur_pos.x][cur_pos.y].v=true;
        return true;
    end
end
function move_east()
    if( cur_pos.x == size.x ) then return false end;
    if( maze[cur_pos.x+1][cur_pos.y].v == true ) then
        return false;
    else
        maze[cur_pos.x][cur_pos.y].e=false;
        cur_pos.x = cur_pos.x + 1;
        maze[cur_pos.x][cur_pos.y].v=true;
        return true;
    end
end
function move_west()
    if( cur_pos.x == 1 ) then return false end;
    if( maze[cur_pos.x-1][cur_pos.y].v == true ) then
        return false;
    else
        cur_pos.x = cur_pos.x - 1;
        maze[cur_pos.x][cur_pos.y].e=false;
        maze[cur_pos.x][cur_pos.y].v=true;
        return true;
    end
end
move={move_north,move_east,move_south,move_west};
function gen_path()
    while (move[cur_pos.dir]()) do
        local dir = math.random(-1,1);
--        print("Dir=",dir);
        cur_count = cur_count + 1;
        cur_pos.dir = (dir+cur_pos.dir-1)%4+1;
--        print(cur_pos.x,cur_pos.y,cur_pos.dir);
    end
end
function new_path()
    cur_pos.x, cur_pos.y = magic_to_pos();
    while (maze[cur_pos.x][cur_pos.y].v == false) do
        cur_pos.x, cur_pos.y = magic_to_pos();
    end
    cur_pos.dir = math.random(1,4);
end
while ( cur_count < total_count ) do
    gen_path();
    new_path();
end
-- print(cur_count);
-- plot maze
im = gd.createTrueColor(grid.x*size.x+1,grid.y*size.y+1);
white = im:colorResolve(255,255,255);
red   = im:colorResolve(255,  0,  0);
green = im:colorResolve(  0,255,  0);
blue  = im:colorResolve(  0,  0,255);
im:line(  0, 0, grid.x*size.x, 0, green);
im:line(  0, 0, 0, grid.y*size.y, green);
for v=1,size.y,1 do
    for u=1,size.x,1 do
        if(maze[ u][v].e) then
            im:line(  grid.x*u, grid.y*(v-1),  grid.x*u,  grid.y*v, green);
        end
        if(maze[ u][v].s) then
            im:line(  grid.x*(u-1), grid.y*v,  grid.x*u,  grid.y*v, green);
        end
    end
end
-- im:png("maze.png");
-- reslove maze
--]]
path={};
search_count = 1;
search_pos={x=start_pos.x, y=start_pos.y, dir=0};
table.insert(path,search_pos);
function read_north()
    if( search_pos.y == 1 ) then
        return;
    else
        if ( not maze[search_pos.x][search_pos.y-1].s ) then
            local node = {x=search_pos.x, y=search_pos.y-1, dir=3, r=search_count};
            table.insert(path,node);
        end
    end
end
function read_south()
    if( search_pos.y == size.y ) then
        return;
    else
        if ( not maze[search_pos.x][search_pos.y].s ) then
            local node = {x=search_pos.x, y=search_pos.y+1, dir=1, r=search_count};
            table.insert(path,node);
        end
    end
end
function read_east()
    if( search_pos.x == size.x ) then
        return;
    else
        if ( not maze[search_pos.x][search_pos.y].e ) then
            local node = {x=search_pos.x+1, y=search_pos.y, dir=4, r=search_count};
            table.insert(path,node);
        end
    end
end
function read_west()
    if( search_pos.x == 1 ) then
        return;
    else
        if ( not maze[search_pos.x-1][search_pos.y].e ) then
            local node = {x=search_pos.x-1, y=search_pos.y, dir=2, r=search_count};
            table.insert(path,node);
        end
    end
end
while ( not (search_pos.x == target_pos.x and search_pos.y == target_pos.y) ) do
    if( search_pos.dir ~= 1 ) then read_north() end;
    if( search_pos.dir ~= 3 ) then read_south() end;
    if( search_pos.dir ~= 2 ) then read_east() end;
    if( search_pos.dir ~= 4 ) then read_west() end;
    search_count = search_count + 1;
    search_pos.x = path[search_count].x;
    search_pos.y = path[search_count].y;
    search_pos.dir = path[search_count].dir;
--    print(search_count, search_pos.x, search_pos.y, path[search_count].r );
end
-- print(search_count, search_pos.x, search_pos.y, path[search_count].r );
r_count  = path[search_count].r;
rr_count = search_count;
while ( r_count > 1 ) do
--    print( path[r_count].x, path[r_count].y );
    im:line(path[rr_count].x*grid.x-grid.x/2, path[rr_count].y*grid.y-grid.y/2, path[r_count].x*grid.x-grid.x/2, path[r_count].y*grid.y-grid.y/2, red);
    rr_count= r_count;
    r_count = path[r_count].r;
end
im:line(path[rr_count].x*grid.x-grid.x/2, path[rr_count].y*grid.y-grid.y/2, start_pos.x*grid.x-grid.x/2, start_pos.y*grid.y-grid.y/2, red);
im:jpeg("r-maze.jpg",100);



GD:迷宮產生器


require "gd"
grid={x=10,y=10};
size={x=50,y=50};
maze={};
for u=1,size.x,1 do
    maze[u]={};
    for v=1,size.y,1 do
        maze[u][v]={v=false,s=true,e=true};
    end
end
math.randomseed(os.time());
total_count = size.x*size.y;
magic= math.random(1,total_count);
cur_pos={};
function magic_to_pos()
    local x,y;
    magic = (magic + 997)% total_count;
    x = magic % size.x + 1;
    y = math.floor(magic / size.x) + 1;
    return x,y;
end
cur_pos.x , cur_pos.y = magic_to_pos();
cur_pos.dir = math.random(1,4);
maze[cur_pos.x][cur_pos.y].v = true;
cur_count = 1;
function move_north()
    if( cur_pos.y == 1 ) then return false end;
    if( maze[cur_pos.x][cur_pos.y-1].v == true ) then
        return false;
    else
        cur_pos.y = cur_pos.y - 1;
        maze[cur_pos.x][cur_pos.y].s=false;
        maze[cur_pos.x][cur_pos.y].v=true;
        return true;
    end
end
function move_south()
    if( cur_pos.y == size.y ) then return false end;
    if( maze[cur_pos.x][cur_pos.y+1].v == true ) then
        return false;
    else
        maze[cur_pos.x][cur_pos.y].s=false;
        cur_pos.y = cur_pos.y + 1;
        maze[cur_pos.x][cur_pos.y].v=true;
        return true;
    end
end
function move_east()
    if( cur_pos.x == size.x ) then return false end;
    if( maze[cur_pos.x+1][cur_pos.y].v == true ) then
        return false;
    else
        maze[cur_pos.x][cur_pos.y].e=false;
        cur_pos.x = cur_pos.x + 1;
        maze[cur_pos.x][cur_pos.y].v=true;
        return true;
    end
end
function move_west()
    if( cur_pos.x == 1 ) then return false end;
    if( maze[cur_pos.x-1][cur_pos.y].v == true ) then
        return false;
    else
        cur_pos.x = cur_pos.x - 1;
        maze[cur_pos.x][cur_pos.y].e=false;
        maze[cur_pos.x][cur_pos.y].v=true;
        return true;
    end
end
move={move_north,move_east,move_south,move_west};
function gen_path()
    while (move[cur_pos.dir]()) do
        local dir = math.random(-1,1);
--        print("Dir=",dir);
        cur_count = cur_count + 1;
        cur_pos.dir = (dir+cur_pos.dir-1)%4+1;
--        print(cur_pos.x,cur_pos.y,cur_pos.dir);
    end
end
function new_path()
    cur_pos.x, cur_pos.y = magic_to_pos();
    while (maze[cur_pos.x][cur_pos.y].v == false) do
        cur_pos.x, cur_pos.y = magic_to_pos();
    end
    cur_pos.dir = math.random(1,4);
end
while ( cur_count < total_count ) do
    gen_path();
    new_path();
end
-- print(cur_count);
-- plot maze
im = gd.createTrueColor(grid.x*size.x+1,grid.y*size.y+1);
white = im:colorResolve(255,255,255);
red   = im:colorResolve(255,  0,  0);
green = im:colorResolve(  0,255,  0);
blue  = im:colorResolve(  0,  0,255);
im:line(  0, 0, grid.x*size.x, 0, green);
im:line(  0, 0, 0, grid.y*size.y, green);
for v=1,size.y,1 do
    for u=1,size.x,1 do
        if(maze[u][v].e) then
            im:line(  grid.x*u, grid.y*(v-1),  grid.x*u,  grid.y*v, green);
        end
        if(maze[u][v].s) then
            im:line(  grid.x*(u-1), grid.y*v,  grid.x*u,  grid.y*v, green);
        end
    end
end
im:jpeg("maze.jpg",100);


2008年12月19日 星期五

定點數小數表示法

主題:定點數小數表示法
使用範圍:使用整數運算系統下之小數運算
參考資料:嵌入式系統構件 Jean J. Labrosse原著 黃文增譯 全華科技圖書出版
原理說明:
先復習一下計算機概論,有許多人都還給老師了。"^"表示次方運算
101.101b=2^2+2^0+2^-1+2^-3=5.625
現在是如何運用到FPGA上了。其實這個問題在之前的定點數DSP就遇過了,只是後來應用變少了。現在的FPGA又要用,捲土重來。
我們知道FPGA對於整數系統的加減法是可以,但是遇到小數有些人就不知該如何。其實不難,只要在整數運算系統上加上小數點就行了。
例如101.1b+101.1b=1011.0b,可以發現去掉小數點就和整數運算沒有兩樣。意指,只要將小數點那個位數對齊就可以了,使用移位對FPGA是很容易的。
但是整數運算使用為小數要標示小數位置,所以引入類似科學記號表示法。我們知道科學表示法為<尾數>E<指數>,例:3E3=3*10^3=3000,E表示10的次方。
定點數的表示法符號為S,表示法為<尾數>S<指數>,S表示為2的次方。舉例2.5S3=2.5*2^3=2.5*8=20。
在基本數學運算下的處理為:
1.加減法
處理方式是將小數位數對齊再做運算。例:10S3+3S2=20S2+3S2=23S2
2.乘除法
乘法時要將指數相加,尾數相乘。例:2S3*3S2=6S5
除法時要將指數相減,尾數相除。例:2S3/3S2=0.66S1
3.開根
主要是推導數學運算對指數的影響。
sqrt(aSb)=sqrt(a)*sqrt(2^b)=sqrt(a)*2^(b/2)
可以發現在開根時指數是除2,尾數直接開根。
4.小數精度的選用
為了符合精度,要如何選用指數範圍。我們使用定點數其精度取決於二進位小數取多少位。
例如若是使用S-4為其指數,每二數之間最小距離為2^-4=0.0625。此為S-4下的精度。
對應十進位精度可以使用log(精度)/log(2)去計算要使用的指數。
使用精度0.1則S取用為log(0.1)/log(2)=-3.32,則使用S-4為其數值格式,就夠用了。
5.數值範圍
因為定點數是有限的位元組成,也是有限的數字集合及有限的可使用範圍,一但超過範圍的數也無法表示。也就是在運算上有可能會產生縊位問題,而造成非預期結果。
所以只可以使用在變動不大的運算上。所以要考量使用的數值範圍及使用精度,這方面是定點數在使用前要考量好的。
定點數應用例:
已知機器運算只能使用整數的狀況下,要使用小數,則是使用負的S指數,將尾數變成整數。尾數送入機器去運算;指數則是人工管理。
例:r=10.1求圓面積area,假設輸出入需求精度為0.1
解答:精度為0.1則,log(0.1)/log(2)=-3.32,故選用的S指數要到S-4可以達成。
pi=3.1416=50S-4(四捨五入)
r=10.1=162S-4(四捨五入)
area=pi*r*r=50S-4*162S-4*162S-4=1312200S-12=5126S-4(四捨五入)
換算為320.375
實際為320.47386659269480825557425152834
只有精準到整數,是因為所有數值精確度只有到0.1,誤差是0.05,運算來源有三個,故最大誤差為0.15,所以符合誤差範圍。
由算式可以得知機器只計算50*162*162,解讀結果需右移8位元含四捨五入,輸出結果為S-4格式。
小技巧:
定點數之計算可以使用小算盤來算。將小算盤設定為工程型。使用二進位顯示就可以將十進位轉成二進位。
因二進位只能使用整數,所以要先轉成整數才可以顯示。
例如:pi的取用。
pi取S-4結果為何?先取出pi=3.1415926535897932384626433832795
若我們使用精度為Qword則有64位元可以用,可以先乘上2^32,取用4相關的指數,可以在顯示時容易找到小數點位置。
結果為13493037704.522018958598982648896
直接按二進位,結果為11 0010 0100 0011 1111 0110 1010 1000 1000
找到小數點位置後可以發現是110010bS-4
輸入110010按十進位可得50,我們可知pi=50S-4
另外pi常有人用201/64來表示,其實是使用S-6的格式,可以看上面的值找出pi=11001001bS-6=201S-6
另外四捨五入在二進位很容易做,只要看取需要取用的小數精度下一位是否為1,若是則結果加一,不是則捨棄。
但會引發另一問題,剛好尾數LSB為多個1連續,則會進位。
以pi為例取S-10至S-15四捨五入後表示的數皆相同,都會和S-10完全一樣,精度沒有增加,pi皆為3217S-10,就算是寫成不同的S值,如12868S-12,仍等於3217S-10。


2008年12月16日 星期二

GD:葉形線


require "gd"
n = 3.1;
m = 20;
size = 200;
im = gd.createTrueColor(size+1,size+1);
white = im:colorResolve(255,255,255);
red   = im:colorResolve(255,  0,  0);
green = im:colorResolve(  0,255,  0);
blue  = im:colorResolve(  0,  0,255);
offset = { x=size/2 , y=size/2 };
last = {};
for u=0, m*math.pi, 0.001 do
    r=size/2.5 * math.sin(n*u) + 10;
    new={ x = r*math.cos(u)+offset.x , y = r*math.sin(u)+offset.y};
    if last.x == nil then
        first = { x=new.x , y=new.y};
    else
        im:line(  last.x, last.y,  new.x,  new.y, green);
    end
    last= {x = new.x , y = new.y};
end
im:line(  last.x, last.y,  first.x,  first.y, green);
im:jpeg("tt.jpg",100);
-- 程式結束
Lua其實還满好用的,很快就可以得到結果了。
又因任http://bbs.luaer.cn/index.php版主,所以寫了點程式交代一下。

開張了

不知是何時有這個空間的。也許是為了問答別人部落格時註冊產生的。即然發現了,就開始用吧!