ホーム » 2011 » 5月 » 17

日別アーカイブ: 2011年5月17日

2011年5月
« 4月   6月 »
1234567
891011121314
15161718192021
22232425262728
293031  

最近の投稿(電子情報)

アーカイブ

カテゴリー

浮動小数点と、文字列数値変換プログラム

先週の整数型の数値範囲の続きということで、浮動小数点の数値の範囲の話の後、 数字の文字列を、N進数の考え方を元に数値に変換したり、 その逆の変換をするプログラムを説明。 来週は、演習室で数値変換の演習。 最後に時間が余ったので、#define 文などの説明を行う。

浮動小数点データの値の範囲

最初に浮動小数点データの正規化を分かってもらうために、 実験データの精度の話を行う。「1.2345の真値と1.222という実験値の誤差を求めよ」 と聞いてみると、みんな1.013%と答える。 でも実際には、桁落ちが発生し誤差を考えると1.0%と2桁で記載すべきことを説明する。

この桁落ちで、有効桁が減ったままだと後々の計算がさらに精度が悪くなるので、 浮動小数点では計算後で桁落ちなどがあった場合、 最初の意味のある桁まで小数点を移動すること…ということで正規化を説明する。

このように指数部を変化させながら…という説明をした後で、floatやdoubleが 以下のように数値を扱うことを説明。

符号(s) 仮数部(e) 指数部(d…) 意味
float 1bit 8bit 23bit
double 1bit 11bit 52bit

文字列数値変換プログラム

次に、文字と文字コード、文字配列、N進数変換を理解するための定番のネタということで、文字列数値変換プログラムの説明。

// 文字列を数値に変換
int my_atoi( char s[] ) {
int ans = 0 , i ;
for( i = 0 ; s[i] != '¥0' && s[i] >= '0' && s[i] <= '9' ; i++ )
ans = ans * 10 + ( s[i] - '0' ) ;
return ans ;
}
// 数値を文字列に変換
#define SINT_WIDTH 5
char* my_itoa( char ans[] , int x ) {
int i ;
ans[ SINT_WIDTH ] = '¥0' ;
for( i = 0 ; i < SINT_WIDTH ; i++ ) {
int d = x % 10 ;
ans[ SINT_WIDTH - 1 - i ] = '0' + d ;
x = x / 10 ;
}
return ans ;
}

いつも授業中には「質問ありません?」としつこく聞くんだけど、授業が終わったら 何人かの学生が、my_itoa の返り値が char* な説明を聞きにくる。 このプログラムでは、printf( "%s" , my_itoa( temp , 1234 ) ) みたいな 使い方を想定していることを説明し、文字配列の先頭(ポインタ)を返していることを 説明。

#define文

説明後に時間も余っているし、来週の演習後に説明予定であった#defineの説明を 行う。プログラム中の利用目的が解らない定数は、一般的にマジックナンバーと呼ばれ、プログラム修正が困難になることを説明し、定数宣言が便利であると解説。

C言語でこれに相当するのが、#define… と言う前に、プリプロセッサ処理を 説明し、Cソース→[プリプロセッサ]→[コンパイラ]→中間コード→[リンカ]→機械語 といった流れも説明する。
#defineマクロについては、演習後に説明の予定。

ずーっと、講義録をMovableTypeでメモしており、数式部分には mimetex.cgi を使っている。しかしながら、MobableTypeのバージョンが上がったためか、最近、数式内で ¥times とかを書くと「¥」にエスケープ処理が入るため、正しく×が表示されない。 TeXで「¥」が使えなかったら、¥frac…ほとんどダメじゃん…