ブログ「サイバー少年」

ブログ「サイバー少年」へようこそ!
小学六年生ごろからプログラミングを趣味にしている高校生のブログです。
勉強したことについての記事などを書いています。フリーソフトも制作、公開しています。
(当ブログについて詳しくは「ブログ概要紹介」を参照)

サイバー少年が作ったフリーソフトは「サイバー少年の作品展示場」へ

浮動小数点数表現のデータを10進数表記にする

でました。
私の嫌いな浮動小数点数。

私は未だに浮動小数点数の知識が曖昧なので、
今日、色々なサイトで勉強しました。

しかし、分からないことが1つありました。
(本音を言えば100くらいある)

浮動小数点数は最終的にどうやって"3.14"などの、10進数の小数になるのか!?

浮動小数点数を2進数の小数にするのは、単純に計算した後、
それっぽくシフトしてピリオドを付けるだけですから、簡単だと思います。

しかし、そこからです!

2進数の小数をどのように10進数の小数にするのか!?

これが分からんのです。

10進数の小数を、2進数の小数に変換する方法は、色んなサイトで書かれているんですよ。

しかし、その逆はどこにも書かれていないんですよね…。


Yahoo!知恵袋に質問しようと思いましたが、そのまえに自分で方法を考えてみました。

結局、まだ質問していません。

その方法をご紹介します。


まず、2進数の小数の整数の部分(1001.101だったら1001の部分)は、普通の整数ですから無視していいわけです。

2進数の小数を10進数の小数に直したあと結合すればいいだけなんですから。

そこで小数部だけに着目します。

頭で計算した場合、2進数の0.11 / 2と同じですから、0.5だと分かります。

2進数の0.011 / 4と同じですから0.25だと分かります。

さて、この作業をなぜコンピュータで再現できないのかと言いますと、
導いた答えが0.5やら0.25やらの小数になってしまうからです。

結局、その小数を扱えませんから、このやり方は無理なんです。


そこで、導いた答えが整数になるように調節すればいいんじゃないかと思いました。

例えば1 / 2じゃなくて、10 / 2としたら5になりますから表現できます。

1 / 4100 / 4としたら25になりますから表現できます。

つまり、1のところを10倍単位で大きくしてやれば、答えを保ったまま整数にできます。


具体的にどうするかというと、

例えば2進数の0.101なら、10 / 2 = 5(中心は0なので飛ばす)1000 / 8 = 125という2つの数を計算して、

50で埋めて500にして、125と足せば625となります。

これは小数部の数なので、0.と付け加えたら0.625となります。
ここは単なる文字列処理ですね。

よって2進数の0.101は10進数の0.625です。


ちなみに、これを考えたあと「50で埋める」作業が無くなるように改善しました。

各桁で登場する10とか1000とかを1つに揃えればいいんです。

先ほどの作業では、一番大きいのは1000でしたから、1000で揃えれば上手くいきます。

2進数で0.101だったので、1000 / 2 = 5001000 / 8 = 125というやり方でやって、500 + 125625です。

しかし「一番大きいのは1000」といっても、実際には一番大きいのはどれか分かりませんし、
本当にそれが一番大きいのかは分かりません。

仕組み上、適当に大きい数(1000000000000000000など)でやれば、まず答えが小数になってしまうことはありませんから大丈夫なんです。

しかし、そうすると最終的に0がたくさんついて、変換結果が0.625000000000000など不自然になってしまいます。
(まぁ、問題ありませんが)


無駄な0がつかず、割ったときに小数にならない数は、
具体的にどう算出すればいいでしょうか。

それも発見しました。

10の“小数部の桁数”乗です。

この数で揃えればピッタリ収まります。

2進数で0.101なら、小数部は3桁ですから103で揃えます。
確かに1000がピッタリな数ですね。

他の数でもいけます。何でも10の“小数部の桁数”乗です。

なぜなのかは分かりませんが、そうなんです。

データもあります。

2-1…0.5
2-2…0.25
2-3…0.125
2-4…0.0625
2-5…0.03125

ご覧の通り、マイナスでの2の累乗で、
指数が1、減っていくごとに桁数は1桁、増えています。

(指数が1、減っていくというのは2進法で0.1, 0.01, 0.001…と、どんどん右にずれていくことを意味しています。)

2-10までしか試していませんが、ずっとこうなんだと思います。


ということは、10の“小数部の桁数”乗がぴったりなんです。


方法も分かったところで、2進数の0.10101を10進数にしてみましょう。

小数部は5桁ですから、揃える数は105、すなわち100000です。

小数点以下第一位から順番に、

100000 / 2 = 50000
0のため無視
100000 / 8 = 12500
0のため無視
100000 / 32 = 3125

という答えを出し、全部足して65625です。

そして、整数部の0.と結合して、2進数の0.10101は10進数では0.65625というわけです。



さてさて、浮動小数点数(2進数の小数)を10進数で表記するには、こんな感じで処理するんじゃないかと考えたわけです。

ただ、あくまでも解説しているサイトがなかったため、自分で考え出した方法です。

実際はこれとは違う方法で行われているのかも知れませんし、まさにこの方法で行われているのかも知れません。

それは私には分かりません。
私が勉強している立場なのですから。

そこにご注意ください。

実際はどんな方法なのか知りたいものです。

tag:

コメント

コメントの投稿

トラックバック

トラックバック URL
http://cyberboy6.blog.fc2.com/tb.php/243-860b5606
この記事にトラックバックする(FC2ブログユーザー)

当ブログをご利用(閲覧等)になる場合は必ず「当ブログの利用規定」をお守りください。