Perl で 実数 2進数 変換Perl の基礎を学習する上で、実数から2進数に変換するプログラムを扱うことにしました。 ハードウェアを設計していて、算術演算回路の符号付きで小数点以下の数値を扱う場合、デジタルなので当然 2進数で演算するのですが、整数から2進数の変換をしてくれる電卓はあるものの、実数から2進数に変換してくれる電卓がなく、いちいち手計算で検証するのは大変です。 そこで、 Perl でプログラムを書いてみました。あとで解説しますが、まずは全体を載せておきます。 なお、このプログラムは以下のように実行します。
第1引数:実数 すると、結果がこのように表示されます。
それでは1つずつ解説していきます。 実行属性の付け方
1行目のこれ↑は 実行コマンドの perl がインストールされている path を指定しています。実行コマンドの perl がどの path にあるかは、以下のように which コマンドで確認します。
#!/usr/bin/perl のように1行目に path を指定しておき、perl の script ファイル (ここでは real2bin.pl) のファイル属性に実行属性を付けておけば、script ファイル名を入力するだけで perl プログラムが実行できるようになります。
これで real2bin.pl という script は実行属性が付きましたので、以下のように実行させることができます。
サブルーチンいきなりですが、3〜9行目にはサブルーチンが定義されています。これは引数も戻り値も持たない簡単なサブルーチンです。
このサブルーチンの目的は、外部引数が必要な real2bin.pl を実行させるとき、誤った引数が与えられたときに表示する syntax error メッセージであり、引数の与え方を忘れてしまったときに、あえて表示させる help メッセージの代わりとなっています。 サブルーチンの書き方として、引数の受け取りの仕方や戻り値の書き方の説明は、長くなるので別のところで説明したいと思います。 外部引数の受け取り11〜18行目に書かれているのは、real2bin.pl に必要な引数の代入を行っています。また、引数として3つが必要なため、3つ以外の引数が与えられた場合はプログラムが終了する仕掛けになっています。
1つ目の引数は、実数です。整数でなく、実数ですから正負の小数点以下の数値を含みます。 なお、2つ目の引数は、2進数で表現するのに十分なbit幅が指定されなければなりません。 負の数の扱い20〜31行目に書かれているのは、コンピューターが負の数を扱うルールに合わせて、引数で与えられた実数を前処理している部分です。
コンピューターの中では、0 と 1 の値しかありませんから、負 (-) を表現するために一般的に使われているルールがあります。それが 2の補数を 負の数として扱うもので、分かりやすく説明するために整数を使って8bitで表現すると以下の数列のようになります。
2の補数というのは、もとの2進数を反転させて+1した数値のことです。 3の2の補数は、3:00000011 を反転:11111100 して +1 した 11111101 です。
桁上がりで8bitの外に出てしまった1を無視すると、2:00000010 が得られました。 さて、3の2の補数:11111101は、そのまま10進数の正の整数で表すと 253 です。これは、2の8乗である 256 を -3 した値です。2の補数がそういうものですから当然です。 ここで、perl プログラムに話をもどして、 なお、引数で与えられた実数が 負の数 でない場合は、与えられた実数をそのまま $p_num に代入しています。 小数部の処理 - 丸め処理33〜41行目に書かれているのは、real2bin.pl に与えられた小数部のbit幅でおさめるために、丸め処理(四捨五入)を行っています。これも2進数に変換する前に処理しておきます。なぜなら、2進数に変換後に四捨五入すると桁上げするためのプログラミングが大変だからです。
例えば 実数の 0.1 を2進数で表すと 0.0001100110011... のように永遠に続く数列になります。 2進数の小数側の数字というのは、重みが桁が下がるごとに、2の-1乗,-2乗,-3乗... となるのですが、実際に数字に直すと以下のようにそれほど小さい数字にならないからでしょう。
このように2進数で小数点以下の数字を表すとbit幅によって精度が変わります。そこで、限りあるbit幅で出来る限り良い精度を求めようとすると 丸め処理が行われるのが一般的です。 丸めは、求める2進数の最下位bitの1つ下位に2進数の1を足すことを行います。例えば、上記の 0.000110011 を 8bit に丸めるとすると、以下のよう 9bit目に1を加えて丸めます。
ちなみに、もし、丸め処理せずに切り捨てになったら、以下のように 0.1 との差が広くなってしまいます。
ここで、perl プログラムに話をもどして、 整数部の2進数変換さて、ここまでで、2進数へ変換する前処理が出来ました。いよいよ2進数に変換します。まずは整数部を変換します。 前処理で 負の数、丸め処理による桁上げ を済ませた数字 $p_integral なので、シンプルな2進数変換が出来ます。
44行目に2進数に変換した後に 0 1 を蓄える配列を初期化しています。 小数部の2進数変換
小数部の2進数変換も整数部と同様に for文で回しながら配列に蓄えて行きます。 演算の仕方は、2倍して1より大きければ 1 、小さければ 0 を配列に蓄えて行きます。このとき、1より大きかった場合は、1を減算します。 最後に演算結果を表示してプログラムは終了です。
|
自己紹介 50才になる半導体エンジニアです。大学で電子電気工学を学び、1990年にその分野のまま就職。ASICやマイコンの設計を長く続けてきましたが20年も同じ分野にいると業態も衰退したり変化するもので退職し、今は外資のIT系会社に再就職して設計請負業をやっております。 お問い合わせは nakata.xianzhi@outlook.com Linux と 小ネタ デジタル回路設計
海外駐在後記
|