2分木で式を表現
2分木の応用として、2項演算子と数値を表現する方法を説明した。
式と表記法
木での表現の前に、式を演算子の優先順位のカッコ無しで表現する手法として、 逆ポーランド記法などを説明する。また、逆ポーランド記法で表記されたデータを 処理する場合にはスタックなどが便利であることも説明する。
中置記法: 1+2*3 逆ポーランド記法: 1,2,3,*,+ (後置記法) 前置記法: +,1,*,2,3
スタックを使えば、逆ポーランド記法データから値を求める処理が簡単。 数値ならスタックに積む。演算子なら2つデータを取って計算し、結果を再びスタックに積む。
| | | | |3| + | | |2| |2| |6| / \ |1| |1| |1| |1| |7| 1 * ------------------- / \ 1 , 2 , 3 , * , + 2 3
2分木で式を表現
struct Expr { int value ; // left,right==NULLの時は数値 char op ; struct Expr* left ; struct Expr* right ; } ; struct Expr* Integer( int v ) { // 数値の木を作る struct Expr* ans ; ans = (struct Expr*)malloc( sizeof( struct Expr ) ) ; if ( ans != NULL ) { ans->value = v ; ans->op = ' ' ; // dummy ans->left = ans->right = NULL ; } return ans ; } struct Expr* Operator( char op , // 式の木を作る struct Expr* l , struct Expr* r ) { struct Expr* ans ; ans = (struct Expr*)malloc( sizeof( struct Expr ) ) ; if ( ans != NULL ) { ans->value = 0 ; // dummy ans->op = op ; ans->left = l ; ans->right = r ; } return ans ; } int eval( struct Expr* e ) { // 木の式を評価 if ( e->left == NULL && e->right == NULL ) { return e->value ; } else { int l = eval( e->left ) ; int r = eval( e->right ) ; switch( e->op ) { case '+' : return l + r ; case '*' : return l * r ; } } } void main() { struct Expr* exp = Operator( '+' , Integer( 1 ) , Operator( '*' , Integer( 2 ) , Integer( 3 ) ) ) ; printf( "%d" , eval( exp ) ) ; }
Moodleネットワーク機能
現在福井高専で運用している Moodle サーバへの機能拡張をするための、 打ち合わせに同席した。現在、f-leccsではシングルサインオンにより、 県立大学に設置されている f-leccs の Moodle サーバは、関係学校より 自由に使える。 こういう2重のMoodleサーバを運用している中で、機能拡張で、 Moodle ネットワーク機能と、携帯でアンケートを取る機能を、見せてもらった。
Moodleネットワーク機能は、他のMoodleサーバにも接続できるようになる機能みたい。 シングルサインオンで使える f-leccs があるから、 必須ではないが、将来的にシームレスに Moodle を連携するときには便利かな。
家庭用向け太陽光発電システムって…
今年度は、福井県機械工業会の方々との連携事業に関係しているけど、 エコがキーワード。講習会では、太陽光発電などの話を聞いているけど、 実際家庭で使う太陽光発電の話が家電Watchで記事になっているので、 メモを残す。
緊急連絡システムのメールでの確認
緊急連絡システムでは、システム全体の利用状況を見るために、 全学校で緊急メールが出されると、管理者用のメールアドレスにも メールを送るようにしてある。 でも、もう一人の管理者の先生から、最近管理者用のメールが届かないとの連絡。 (私は熊の季節には、あまりにも数多いメールが来るので、自分宛ははずしておいた)
確認してみると、最近情報処理センターのメールシステムの更新で、 管理者用のメールアドレスから、実際の管理者へのメール転送機能が設定されていなかったのが 原因だった。 ということで、センターの方に転送の設定方法を聞いて設定。 実際は、usermin(webmin)で、.forward ファイルを編集する。 usermin には、.forwardファイルを直接書き込む設定があったので、 .forward ファイルの書き方を確認しながら、転送設定を行った。
メモリ階層とネットワークの基礎
先週の授業で、OSに関係する部分の説明を終えていたが、 メモリ階層の話が抜けていたので補足。
メモリ階層
コンピュータで利用するデータには、局在性があり よく利用するデータと利用頻度の低いデータがある。 これに応じてコンピュータでは、高速・高価なメモリと、低速・安価なメモリを うまく使い分けることで、「見かけ上、高速なメモリが大容量あるようにみせる」 メモリ階層は、 (a)もっとも速く利用頻度の高いCPU内部の汎用レジスタ(多くても数百バイト)と、 (b)キャッシュメモリ(数キロバイトでS-RAMを使う)、 (c)主記憶(数ギガバイトでD-RAMを使う)、 (d)補助記憶装置(ハードディスクの仮想メモリ)で、遅くて大容量。 を使い分けている。

ネットワークの基礎
計算機システムのOSネタの後半は、ネットワークについて説明を行う。 最初に、ネットワークの利用目的として、共有・分散をキーワードに、説明を行う。
- 資源共有(資源分散)
-
ハードウェア資源を共有。プリンタサーバ(ハードウェアの共有)、 ファイルサーバ(データの共有・ハードディスクの共有)。 アプリケーションサーバ(アプリケーションの共有,ライセンスであんまり使われていないけど)
- 負荷分散
-
ムーアの法則で、コンピュータ処理速度は限界に達している。 さらなる高速化のために、計算処理を複数のコンピュータで分散して実行する。 グリッドコンピューティングやクラウドコンピューティングなど。
- リスク分散
-
ネットワークの歴史的には、Internetの元のARPANETなどは、軍の中央コンピュータが核ミサイル破壊で、全体が動かなくなるリスクを、別なコンピュータで代用できるようにした所が始まり。現在でもコンピュータの故障リスクをなくすために、複数台で処理することが普通。 クラウドもリスク分散を兼ねている。
ネットワークの歴史として、 (1)TSSによる端末・サーバ間通信、 (2)ARPANETによるネットワーク基礎の確立、 (3)LANの発達、 (4)LAN間接続でWANの発達、 (5)WWW(World Wide Web)の発達 を紹介。
ネットワーク物理層
パソコン・周辺装置インタフェースとして、パラレル接続(高速・ケーブル配線が手間)・シリアル接続(低速・ケーブル配線が容易)がある。 シリアル接続の中で、Ethernetは接続の代表格で、 10BASE/2,5 では、同軸ケーブル接続が基本。 しかしターミネータの必要性から、接続機器の追加削除が不便だった。 10BASE/Tで、間にHUBを置いて分岐する。 10BASE/Tは、100BASE-TX、1000BASE-??と発達している…
2010年11月7日(第189回)
- 福井高専の工場見学旅行と就職活動の関係
- 学内合同企業説明会について
Apache+SSL起動でパスフレーズ入力を…
学科のサーバでは、UPKIオープンドメイン証明を使用しているが、 登録時にパスフレーズを埋め込んでいるために、サーバ起動時に いつも入力待ちになっていた。 ちょいとググったら、技が載っていたので、メモ&設定。
# うほ、便利…
MacでARToolkit、UVCカメラNGだった
来年のプロコンや、画像処理関係の卒研のテーマの導入に使えないかと、 ARToolkitを使おうと準備中。 手元のMacでいつでも実験…と思い環境を整備するけど、まだまだ準備段階。
参考資料
- ARToolKit on Mac OS X(特にVRML)
-
この資料に沿って、OpenVRMLをインストールしてコンパイルをかけてみたけど、 以下のようなエラーメッセージで止まるなぁ。 jpegのライブラリが見つけられていないみたい。
Directory 'sw/lib' following -L not found Library not found for -ljpeg
UVCカメラNGだった
また、動かしてみたサンプルプログラムで試しているけど、 MacのiSight だと、カメラを好きな方向に向けられないので、 USB接続の手持ちのUVCカメラ "Creative Labs VF0280 Live! Cam Optia AF"を接続してみた。 カメラの認識確認で、iChat を起動するけど、普通に認識してカメラは動いた。 しかしながら、ARToolkit のサンプルプログラムを動かして、Source を切り替えるのだが、 どうもサンプルプログラムでは認識してくれない….
# どうももう少し実験の手間がかかりそうだ…
ワード境界とビットフィールド
構造体を使った演習も終わってるので、ワード境界とビットフィールドについて説明する。
32bitコンピュータであれば、CPUとメモリのデータのデータのやり取りは、4byte=32bit単位で 一括して行う。このため、ワード境界にまたがったデータの配置が行われると、 処理速度の低下につながる。授業では、構造体で"char a[9] ;" があった場合の説明を行う。
処理速度重視ならワード境界配置、メモリの効率よい利用であればワード境界無視(Visual C++なら"#pragma pack"らしい)だけど、年月日のデータをy=int,m=int,d=int なら、96bitになるけど、 y=0..2047,m=1..12,d=1..31で考えれば、20bitで表現も可能となる… ということを説明して、ビットフィールドを説明する。 授業では、組み込み系プログラミングなどでは相変わらずシフト演算や&(AND)や|(OR)を 使った計算も理解の必要もあるし、2進数計算の例も説明する。
Arduinoで3軸加速度センサーを使ってみた
今日から、専攻科1年の4週実験が始まった。 Arduinoを使って制御をテーマに実験をおこなってもらう。 実験の概要説明の後、歯みがきロボコンで使ったオムニホイールやら、 興味があったら触ってもらおうと購入しておいた、3軸加速度センサーの 説明を行い、自分たちのテーマを決めてもらった。 簡単なArduinoの実験後の相談で、オムニホイールの車体制御に決まったようだ。
3軸加速度センサーの実験
学生さんが3軸加速度センサーを使わないことが決まったので、 プロコンなどでも使ってもらうために、こちらで実験してみる。 購入しておいたセンサーは、MMA7260Q搭載三軸加速度センサモジュール。 データシートを見ると、Vcc=3.3[V]となっているので、以下のように配線した。
(( MMA7260Q )) Vcc : 3.3[V] GND : GND(0V) X : A0 Y : A1 Z : A2 GS1 : GND // 1.5Gまでの測定の場合 GS2 : GND *SLP: 3.3[V] // SleepさせないのでHIGH

動作確認のためのプログラムで、以下を記述。
void setup() { Serial.begin( 9600 ) ; } int x = 0 , y = 0 , z = 0 ; void loop() { x = analogRead( 0 ) ; y = analogRead( 1 ) ; z = analogRead( 2 ) ; Serial.print( x ) ; Serial.print( "," ) ; Serial.print( y ) ; Serial.print( "," ) ; Serial.println( z ) ; }
このプログラムを動かすと、加速度なしの状態で330〜350ぐらいの範囲で 激しく変動している。1G加速度方向では500ぐらいの値が出ている。 このままではノイズが激しいし、オフセットを引いてノイズ除去を行った。 指数移動平均 の手法(α=1/16)を使用。
int base = 335 ; // 中心値 int x = 0 , y = 0 , z = 0 ; void loop() { x = (15 * x + (analogRead( 0 ) - base) ) / 16 ; y = (15 * y + (analogRead( 1 ) - base) ) / 16 ; z = (15 * z + (analogRead( 2 ) - base) ) / 16 ; Serial.print( x ) ; Serial.print( "," ) ; Serial.print( y ) ; Serial.print( "," ) ; Serial.println( z ) ; }
この状態で、平置きするとZ軸方向で165の値が得られた。 様々な方向にブレッドボードを移動して、方向に応じた加速度の変化も確認できた。
# それにしてもノイズ変動が大きいなぁ…
Processing + Firmata
試しに、Processing でデータを収集しながら、表示するプログラムを手抜きで 書いてみた。
Arduinoには、"SimpleAnalogFirmata"を書き込んでおく。
[開く]-[Firmata]-[SimpleAnalogFirmata] で Compile & Writeしておく。
(( Processing )) import processing.serial.* ; import cc.arduino.* ; Arduino arduino ; color black = color( 0 , 0 , 0 ) ; color white = color( 255 , 255 , 255 ) ; void setup() { size( 400 , 400 ) ; println( Arduino.list() ) ; arduino = new Arduino( this , Arduino.list()[ 0 ] , 57600 ) ; } int m = 335 ; int x = 0 , y = 0 , z = 0 ; void draw() { background( white ) ; stroke( black ) ; x = arduino.analogRead( 0 ) - m ; y = arduino.analogRead( 1 ) - m ; z = arduino.analogRead( 2 ) - m ; //println( x + "," + y + "," + z ) ; int xx = int( x * sqrt(3.0)/2.0 - y * sqrt(3.0)/2.0 ) ; int yy = int( - x * 0.5 - y * 0.5 + z) ; line( 200 , 200 , 200 + xx , 200 - yy ) ; }
もっとサクサク動くかと思ったが、カクカクだなぁ。 draw() だと、リアルタイムに描画処理の中から呼び出されないかな… Processingを使い込んでいないからなぁ…