2015年5月28日 星期四

Raspberry Pi : 安裝Raspbian

準備好USB介面的鍵盤跟滑鼠(我是用Logitech MK240),接條網路線(RJ45),還有無線網卡(我買了白色TOTOLINK N150USM,是mt7601,不要跟黑的搞混了),電源就用我手機的旅充湊數,再把家裡的電視搬過來接,就可以準備安裝了。

安裝第一件事就要先準備已經有Raspbian的MicroSD,官方建議Micro SD的規格為需要大於4GB,且為Class 10 (讀寫速度10MB/s)以上

依照官方網頁應該會很簡單:
https://www.raspberrypi.org/documentation/installation/installing-images/linux.md
(不過我遇到的問題是SD card adapter挑片抓不到我的micro SD,換了台電腦才抓到)

然後是安裝無線網卡,這張在kernel <3.19是起不來的,所以要先抓kernel回來。
wget http://github.com/raspberrypi/linux/archive/rpi-3.19.y.tar.gz
然後按照官方網頁的說明照做即可,建議用cross compiling(因為用pi編譯要很久,我是讓他跑了一晚上。)
若是因為像我一樣讀卡機挑片所以無法直接讀取SD卡,可以用nfs:
pi這邊安裝nfs server:

#sudo apt-get install nfs-kernel-server nfs-common 
#sudo vi /etc/exports 

/      192.168.8.0/24(rw,sync,no_subtree_check,no_root_squash)
/boot  192.168.8.0/24(rw,sync,no_subtree_check,no_root_squash)

#sudo service rpcbind restart #sudo /etc/init.d/nfs-kernel-server restart


若是遇到如下的錯誤訊息:
rpc.mountd: svc_tli_create: could not open connection for tcp6
rpc.mountd: svc_tli_create: could not open connection for udp6
rpc.mountd: svc_tli_create: could not open connection for tcp6
rpc.mountd: svc_tli_create: could not open connection for udp6
rpc.mountd: svc_tli_create: could not open connection for tcp6

可以編輯/etc/netconfig,mark掉兩行:
udp        tpi_clts      v     inet     udp     -       -
tcp        tpi_cots_ord  v     inet     tcp     -       -
#udp6       tpi_clts      v     inet6    udp     -       -
#tcp6       tpi_cots_ord  v     inet6    tcp     -       -
rawip      tpi_raw       -     inet      -      -       -
local      tpi_cots_ord  -     loopback  -      -       -
unix       tpi_cots_ord  -     loopback  -      -       -
 
 


記得開啟nfs service:
pi@raspberrypi /var/log $ sudo /etc/init.d/nfs-kernel-server start
[ ok ] Exporting directories for NFS kernel daemon....
[ ok ] Starting NFS kernel daemon: nfsd mountd.


然後另外一台電腦(我用linux)mount pi的SD card,像這樣:
sudo mount 192.168.1.21:/ /mnt/pi -t nfs

如果遇到以下訊息,請用apt-get安裝nfs-common。
mount: wrong fs type, bad option, bad superblock on 192.168.1.19:/home/shared, missing codepage or helper program, or other error (for several filesystems (e.g. nfs, cifs) you might need a /sbin/mount. helper program)

掛載無誤就能用df看到它了
192.168.1.19:/ 15417856  4941184  9799936   34% /mnt/pi

最後就是無線網卡driver,可以從這邊下載:https://github.com/porjo/mt7601
照著上面的步驟應該就OK了。要記住kernel版本一定要3.19以上阿(3.18 try了N次都不過的人留)。






2015年5月25日 星期一

幾個有趣的問題(來源:PTT C_AND_CPP 精華區)

1.

long int a, b, c;
a= 40000L;
b= 60000L;
c= a*b;

printf("c= %ld\n", c);
// 請問,c= ???, why?


這題要注意的是:
- long int 的大小是 4 bytes (32 bits)或 8 bytes (64 bits),所以 signed long int能表現的最大值為 2^31-1 = 2147483647 (32 bits) 或 2^63-1 = 9223372036854775807L (64 bits)

- 所以如果是在64 bit 電腦上,c當然沒有疑問是2400000000L。可是在32 bit電腦上,這個數字已經超過該type可以表示的極限,所以就會造成溢位(overflow)。

- 可是overflow之後的表現屬於undefined behaviour,意思是說編譯器怎麼做都可以。

2.

long a, b, c;
a= 10;
b= a + 1;// b= 11, > a

while (b > a) {
   a++;
   b+= 1;
}

printf("a= %ld, b= (a+1)= %ld\n", a, b);
// 請問, a= ???, b= ???, why?


- 這個問題比較簡單,同上一題,會run到溢位為止。
- 至於溢位以後的動作一樣是undefined behaviour
(我的電腦跑出的結果是a= 9223372036854775807, b= (a+1)= -9223372036854775808 )

3.

double a, b, c;
a= 4.0*atan(1.0);// a= 3.1415926 ...
b= a + 1.0;// b= 4.1415926 ..., > a

while (b > a) {
   a*= 1.001;
   b= a + 1.0;
}

printf("a= %.3lf, b= (a + 1.0)= %.3lf\n", a, b);
// 請問:a= ???, b= ???, why?

- standard C 並沒有規定浮點數的儲存方式,這跟各家平台對於浮點數的儲存有關,也就是說跑出的結果是implementation defined。我的機器跑出的結果是
a= 9026451774346548.000, b= (a + 1.0)= 9026451774346548.000
- 若浮點數為 IEEE754 則答案會在剛超過 2^53 (9007199254740992) 時停止。

4.

1 不是質數,請問:從 1 to 1,000,000
一共有幾個質數?

使用 什麼方法最快?
你的計算時間是多少?精確度要 小於 0.1秒。


這題有幾個重點:
- 計算時間:C的time.h 只能提供精確度到秒級的時間處理。若需要毫秒級的時間處理可使用Linux提供的<sys/time.h>

http://jyhshin.pixnet.net/blog/post/26587986-linux-%E6%99%82%E9%96%93%E8%99%95%E7%90%86

- 找質數不外乎兩種方法:
循序搜尋法(Sequential Search):一個一個跟找到的質數比較看能不能整除,不能就加入質數List...時間複雜度為O(N^2)
篩法(Sieve of Eratosthenes):把已經找到的質數倍數先篩去,再從剩下的找質數再繼續篩(快多了)。時間複雜度為O(NloglogN)

以下為我用這兩種算法做的參考答案(使用C):
https://gist.github.com/gnitnaw/9db341d4588ff5431c45

5.

100 的 階乘是多少?
要精確到 每一位?

這裡要用大數進行計算(int和long都不夠位數)。
我是直接創造一個可以擁有無限位數的class
https://gist.github.com/gnitnaw/79ccbac48a22e14b67c4
得到結果:
100!= 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

6.

強迫使用遞回呼叫的方式求 費氏數列。
第幾項: 0, 1, 2, 3, 4, 5
答案:   1, 1, 2, 3, 5, 8, 13, . . .

請問:第 100項的答案是 多少?
必須精確到 每一個 位數,

請問:你的程式 需要花多少時間完成?
精確度要 小於 0.1秒

這題不但要用大數計算還要推估大概計算時間
我是算到N=35以後用T(N)=T(N-1)+T(N-2)推算N=100的情況。
答案:
F(100) = 354224848179261915075,
所需時間推估為247170233002558582087us ~ 247170233002558582 ms
(靠!要7837716年)

7.

使用 辛普森的方法求 數值積分,
y= sin(x), x= 0 to pi 的積分值是多少?
pi= 4.0*atan(1.0)

小數點的要求是 %.22lf

0 to pi 的等分 區間數量是 n

n= 10 to 50 step 2

求出 每一個 n 所對應的 積分值?

這個不算難,一下子就寫出來了
https://gist.github.com/gnitnaw/56c6686fcbeb0c9eb3ed
N = 10, Surface = 2.0000067844418008000673
N = 12, Surface = 2.0000032688771600675182
N = 14, Surface = 2.0000017635025444384667
N = 16, Surface = 2.0000010333694131503535
N = 18, Surface = 2.0000006449719771595142
N = 20, Surface = 2.0000004230931827109430
N = 22, Surface = 2.0000002889414907336629
N = 24, Surface = 2.0000002039921938035150
N = 26, Surface = 2.0000001480922562357989
N = 28, Surface = 2.0000001100950042243198
N = 30, Surface = 2.0000000835398590304237
N = 32, Surface = 2.0000000645300017865225
N = 34, Surface = 2.0000000506327708649223
N = 36, Surface = 2.0000000402833366663913
N = 38, Surface = 2.0000000324482267721748
N = 40, Surface = 2.0000000264287591811296
N = 42, Surface = 2.0000000217426348037009
N = 44, Surface = 2.0000000180506227742683
N = 46, Surface = 2.0000000151100518763769
N = 48, Surface = 2.0000000127446351250171
N = 50, Surface = 2.0000000108245044039279


參考資料:
- http://www.csie.ntnu.edu.tw/~u91029/Prime.html
- PTT C_AND_CPP 精華區

2015年5月19日 星期二

C/C++ 小知識(一)

參考資料:PTT C_AND_CPP 精華區

implementation-defined :
The consequence of some certain syntax is desided by compiler, not standard of C/C++. The compiler is obligated to tell you how to define it.
某些語法的執行結果並沒有在C/C++標準中定義,而是由編譯器決定。
但編譯器有義務告知這些定義。

unspecified :
standard C/C++ doesn't define the rule (or give a robust definition), but the compiler will decide it without obligation to inform you.
由編譯器決定如何處理某些語法以達到符合C/C++標準的結果,但無義務告知。

undefined behavior :
Some syntax which the compilers can do what ever they want with them because standard C/C++ doesn't define it.
指C/C++標準未定義其表現的敘述,可編譯但編譯器想怎樣就怎樣。
編譯器不會指出這些語法有問題,但這會是潛在的炸彈。

2015年5月15日 星期五

樹莓派 (Raspberry Pi) 簡介

拖了好久才補心得文...

樹莓派 (Raspberry Pi) 是一個廉價(我買的時候花了35歐元左右,現在二代出了應該更便宜)又只有信用卡大小的迷你電腦,由英國的樹莓派基金會開發。只要買一般usb介面的鍵盤滑鼠接上,在加上一台有hdmi接頭的螢幕或電視就能當電腦用了。

在樹莓派上,你可以寫程式、上網(不過如果要無線上網的話要另外買無線網卡)、看高畫質影片、做文書處理、甚至打電動。

我買的是model B+,所以以下就只針對這型號昨介紹。

系統單晶片(System on chip):Broadcom BCM2835
這是俱備多媒體與高畫質(1080p30 Full HD)應用以及低成本的系統單晶片,支援HDMI輸出與高速高解析度camera的影像解析。

CPU : 700 MHz single-core ARM1176JZF-S (ARM v6)

GPU : Broadcom VideoCore IV @ 250 MHz (支援1080p與高解析度camera,Nokia 808 PureView也是用這款GPU),OPENGL ES 2.0

記憶體(Memory):SDRAM 512MB (與GPU共享)

USB 2.0 接口:4個 (model B+的過流保護跟熱插拔支援較好)

影像輸入:15-pin MIPI camera interface (CSI) connector

影像輸出:HDMI,最高解析度可達1920*1200

音源輸入:I2S

音源輸出:3.5mm TRS端子(一般電腦輸出那種),I2S,或轉為HDMI輸出

資料儲存裝置:MicroSD

額定功率:600 mA (3.0 W)

網路:10/100Mpbs ethernet (RJ45)

外設(Low-level peripherals):40 pins GPIO,包含UART與I2C,+3.3 V, +5 V,接地端

電源:5V (Micro USB 或GPIO)

重量:45 g


參考資料:
http://en.wikipedia.org/wiki/Raspberry_Pi
https://www.raspberrypi.org/help/what-is-a-raspberry-pi/
https://www.raspberrypi.org/products/model-b-plus/

Google Code Prettify