数値の範囲と型
構文,変数の話をしたので、続いては数値範囲について解説。
変な動きのプログラム例
(( 平均を求める処理 )) int a[ 3 ] = { 10 , 10 , 20 } ; int s = 0 , i ; for( i = 0 ; i < 3 ; i++ ) { s += a[ i ] ; } printf( "%f" , s / 3 ) ; // 13.3333 ? (( 簡単な三角関数の計算 )) printf( "%f" , tan( 1/4 * 3.141592 ) ) ; // 1.0 ? (( 2点間の距離を計算 )) // 以下の計算を16bitコンピュータで実行したら... int x0 = 100 , y0 = 100 ; int x1 = 300 , y1 = 300 ; int r = sqrt( (x1-x0)*(x1-x0) + (y1-y0)*(y1-y0) ) ; printf( "%d" , r ) ; // 200*1.4142 = 282.84 ?
上記のプログラムは、どれも期待した答えが求まらない。 その理由を考える。
2進数でN[bit]の桁数があったら、1bitで2とおり,2bitで4とおり,Nbitで、 通りの状態を表せる。 これを数値として考えれば、2bitであれば00=0,01=1,10=2,11=3 として扱えばいい。 よってN[bit]の符号なし整数であれば、 0〜
の数値を扱える。
負の数を扱いたい場合には、最上位bitを符号を表すbitとして考え、 2の補数表現を用いる。2の補数表現は、引き算を足し算だけで扱える。
x = 10 で 8[bit]の場合 0000,1010 = 10 = x + 1111,0101 = (1の補数) ~x で表現 ------------ 1111,1111 = x + (~x) = 全bit1 + 0000,0001 ← 1を加えたら ------------ 1,0000,0000 = x + (~x) + 1 = 0 ただしN[bit]まで よって、(~x) + 1 = -x 負の数の表現に便利
2の補数表現によるN[bit]の数の場合、 〜0〜
を扱うことができる。
この他に、2000年問題と、unix時間が1970年からの経過秒数で表現していることによる、 2038年問題を説明する。
WebサーバのCGI実行のトラブル。
5年の実験にて、CGIを使った処理が動かなくなったとの指摘があり、 あらためて、そのサーバの /var/log/apache2/error.log を確認。 すると以下の様なメッセージが残っていた。
Mon Apr 22 12:21:20 2013] [crit] [client xx.xx.xx.xx] (13)Permission denied: /home/xxxx/xxxx/public_html/.htaccess pcfg_openfile: unable to check htaccess file, ensure it is readable
よく解らないので、"permission denied pcfg_openfile unable to check htaccess…"で検索すると、下記のページが見つかる。
http://d.hatena.ne.jp/memdhoi/20100425/1272195882
ポイントは、<Directory />…</Directory>で、 AllowOverride Allになっていて、 上位ディレクトリの .htaccess が読めないのが 原因みたい。上記サイトの例のように、AllowOverride None に 変更することで、無事動き出す。
今までは AllowOverride が yes の時に、.htaccess が無くても 動いていたものが、apacheのセキュリティ方針の変更の中で、 厳密に上位ディレクトリの .htaccess を確認するように なったみたい。
4/27(土)にネットワーク工事
4/27(土)に、総合情報処理センターにて、 仮想サーバ群のメンテナンス作業が行われます。 このため、下記の日程にて学外からWebなどの サービスが一時的に停止します。
学内でもWeb閲覧・メール送配信にも影響があります。
日時: 2013年4月27日(土) 10:00〜14:00 (実質の停止時間は1時間程度と思われます)
学科サーバの対応
上記のネットワーク作業に伴い、ネットワーク監視ソフトnagiosも 停止させないと、復旧時に大量のメールが舞い込む。
ということで、自分が管理しているサーバ群で、
# echo "/etc/init.d/nagios3 stop" | at 10:00 04/27/13 # echo "/etc/init.d/nagios3 start" | at 14:00 04/27/13
を実行しまくる。
創造工学のアイデアネタ(カード織り)
何気なく、Webを見ていたら、大人の科学で面白い商品が紹介されていた。 んで、その紹介ビデオを見ていたら、昔、NHKのものづくり系の番組で 紹介されていて、実際自分でも試したことがある手軽な織物(カード織り)が、 これまた大人の科学で紹介されている。
女の子のチームでこういう織物のシミュレータ、織物レクチャ環境つくらないかな…
創造工学演習予備実験・通信関係の実験
今年度のプログラミングコンテストは、サイコロを使ったデータ伝送なので、 通信に関係する基礎実験を行うこととする。
通信では、データ伝送時にノイズの発生などで、相手側にデータが正しく 届くとは限らない。今回のプロコンでも、サイコロのコードに変換する作業は 人間が行うことから、違う情報となって送られる可能性が高い。
- send-recv.cxx(漢字コードはShift-JIS)
このことから、今回の実験は、与えられた1行データを 自分なりの間違いチェック情報を付けて送信し、受信時で元に戻して復号するための プログラムを作る。ただし、通常のWindowsのパソコンで実験ができるように、 実際の通信を行う訳ではなく、以下の様に仮想的に関数で変換しながら行う。
- プログラムは与えられたファイルから1行づつデータを読む。
- この1行データは、encode(out[],in[]) によって呼び出される。 あなたは、入力したデータが後のdecode()で戻せるように、 チェックのための情報を付加し、out[] に格納する。
- この作られたデータは、本来なら通信路に送り出されるが、 簡単な実験なので、実験用の関数でノイズを加えられる。
ノイズの処理では、一定の確率で文字が欠落したり重複する。 さらに、一定の確率で文字の各ビットが反転する。 - このノイズが加えられたデータを受信したとして、 あなたは、付加されたチェック情報をみて、正しく送られたか確認しながら、 もとに戻す、decode(in[]) の処理を記載する。 ノイズが加えられ、元に戻せずもう一度データが欲しい場合は、 decode()の返り値として1を返すこと。 同じデータに対し、改めて異なるノイズが加えられたうえで、 もう一度decode()が呼び出される。
上に示した、send-recv.cxx には、必要な処理が記載されているので、 この中の encode( out[],in[] ) と、decode( in[] ) の中身を作成せよ。
レポートに記載する内容
- send-recv.cxx の 関数 encode() , decode() のプログラムリスト
- と、その説明(チェック方法および間違いが発生したらどうなるかの説明)。
- その実験結果。ノイズは乱数を元にしているため、複数回実験を行い、 正しく伝送されているか検証すること。
- 実際にサイコロで情報を伝達するとして、文字をどのようにサイコロで 表現可能か『手法の一案』を示し、さらに人間が並べる作業でミスがあったら、 どういった現象が発生する可能性があるか、発生しうる様々な状況を考察せよ。
レポートでは、実際に簡単な英単語を変換した例と、サイコロを間違えた例を示し、 ミスをチェックできることを確認せよ。
オーダ記法と再帰方程式
前回の授業で、単純サーチ、2分探索法、最大選択ソートの 処理時間の一般式を示した。今回は、これをアルゴリズム の比較という視点で、オーダ記法の説明を行う。
オーダ記法
オーダ記法とは、データ件数Nが巨大であった場合に、 処理時間がどういった式に依存するのかをビッグオー に合わせて、O(N),O(log N),O(N^2)などと記載する方法。 Nが巨大になった時の最大項について、Nの式以外の 定数項を省いた式となる。
複雑な一般式のオーダ記法として、最大項を判断するために、 lim を用いて、ロピタルの定理などを使う方法を説明する。
再帰方程式
次に、再帰処理の処理速度分析について説明する。
// 階乗 int fact( int x ) { if ( x <= 1 ) return 1 ; else return x * fact( x - 1 ) ; } // 変な再帰 int foo( int x ) { if ( x <= 1 ) { return 1 ; } else { int s = 0 ; for( int i = 1 ; i <= x ; i++ ) s += i ; return s + foo( x - 1 ) ; } } // フィボナッチ数列 int fib( int x ) { if ( x <= 2 ) return 1 ; else return fib( x - 1 ) + fib( x - 2 ) ; }
このプログラムの処理時間を分析するための再帰方程式を示す。 最初の2つについては、代入を繰り返すことで、一般式を示すことは容易である。
最後に、再帰方程式の応用として、ハノイの塔の再帰方程式を示す。 次回までに、この再帰方程式を解く方法について予習しておくように伝える。
変数のスコープと寿命
先週のC言語の制御構文の話に続き、変数のスコープと寿命について 説明を行う。
大域変数の問題
最初に、局所変数などの利点を分ってもらうために、 以下のコードの誤解について説明する。
// for文の繰り返しが動かない例。 // 2回の繰り返しを2回で4回表示にはならない int i ; void foo() { for( i = 0 ; i < 2 ; i++ ) printf("A") ; } void main() { for( i = 0 ; i < 2 ; i++ ) foo() ; }
大域変数を多用すると、違う意味で同じ変数を使う 危険性があり、プログラムが動かなくなる。 こういう時には、関数内で局所変数を使い、 同じ名前で違う入れ物の変数を活用する。
局所変数は、通常そのブロックに入る時に、 変数の入れ物が作られ、 そのブロックを抜ける時に、変数が消えてなくなる。 このような、変数が作られる/消えるタイミングを寿命という。
また、局所変数は、そのブロック内でのみ有効であり、 その変数が使える範囲・見える範囲をスコープと呼ぶ。
自動変数と静的変数
以下のような例で、変数の使い方の違いを3種類示す。
int x = 123 ; // 静的大域変数 // 寿命は、プログラム起動から停止まで // スコープは、プログラム全体。 void foo() { int x = 234 ; // 動的局所変数 // 寿命は、関数に入って抜けるまで // スコープは、foo() の内部のみ } void bar() { static int x = 345 ; // 静的局所変数 // 寿命は、プログラム起動から停止まで // スコープは、bar() の内部のみ }
関数の仮引数と実引数
関数呼び出しでは、実引数の内容が、仮引数にコピーされるだけ。 以下のコードでは、「foo() の x++」は、仮引数のxが変化するだけ。 mainのxの値が変化することはない。
int foo( int x , int y ) { // x , y は、仮引数 x++ ; return x + y ; // 返り値の方は、関数の前に書く。 } void main() { int x = 123 ; printf( "%d" , foo( x , 10 ) ) ; printf( "%d" , foo( x , 20 ) ) ; }
大域変数を使うと、関数を呼び出しても、値の変化が発生するかもしれない。 関数を呼び出した影響が、他の部分に及ぶことは、''副作用''と呼ばれる。
新入生ガイダンスでインターネット・携帯の使い方
高専の新入学生へのガイダンスで 「インターネット・携帯の利用上の注意」の説明をしてきました。 10分押しで始まった中、30分予定なのに45分しゃべってしまった。 F主事、I先生、ごめんなさい…(x_x;;
でも、インターネットを使い始めた人への注意点を、 網羅的にトピックを話せたと思う。
- ウィルス対策やワンクリック詐欺対策
- 著作権と肖像権とダウンロード違法化・リッピング違法化
- SNSのマナーと個人情報開示やの怖さ
- 学校内での携帯電話利用のマナーと、インターネット/携帯の依存症
大きな声で、居眠り学生も少なく話せたから、 時間押しを反省しつつも、うまくいったことにしておこう。m(_ _)m