浮動小数点型

ヴァルドルフICTカリキュラム

浮動小数点型

Created by Masashi Satoh | 31/01/2026

  • 本記事は機械翻訳のための原稿として作成しました。そのため、日本語としてはやや不自然な表現となっている箇所がありますこと、ご了承下さい。
  • 上記の理由およびわたし自身の考えから、日本で一般的な「シュタイナー教育」は「ヴァルドルフ教育」で表記を統一しています。

はじめに

本記事は「データモデルの学び」を補強するものです。

浮動小数点型の学びを取り上げる当たって、次のような方針を立てたいと思います。

浮動小数点型を、ここまで学んできた整数型の拡張型として取り扱うこととします。仮数部と指数部を一体のものとは考えず、それぞれ独立した整数型として取り扱います。

指数部が正の場合はその桁数分だけ仮数部を右シフトしていることを示し、負の場合はその桁数分だけ左シフトしていることを示しています。仮数部を2の補数として扱うことで負数を表現することにします。このモデルでは符号部は仮数部に統合されているため、あえて触れません。

この方針に従うと、浮動小数点型の標準形式であるIEEE 754とは異なるモデルについて学ぶことになります。これは、なるべく単純なモデルを扱うことで、生徒たちがシンプルに浮動小数点型の考え方に入っていくことができるようにするためです。

ひととおり学んだあとで、必要に応じて、実際のコンピュータに広く普及しているIEEE 754に触れ、ビット資源の節約の仕掛けやソートなどの効率性を考慮した仕組みが盛り込まれていることをざっくり説明すればよいでしょう。

わたしたちは世界をどのように認識しているか

浮動小数点型の学びのだいご味は、その学びが哲学的な認識論につながることです。いくつかの事例を取り上げて、わたしたちが世界をどのように認識しているのかを考えます。まず、視覚に限定して考えてみましょう。

わたしたちが山を遠くから眺めると、青くかすんだその山の全容が視界に入ります。翌日、ピクニックでその山に向かうと、近づくに連れ、山はわたしたちの前に立ちはだかるようにそびえ立ち、わたしたちの視界を覆います。そこに見えるものは、その山の植生や露出した山肌の地質などです。さらに近づけば、個々の木々の枝ぶりや地を覆う緑のコケとシダ、落ち葉や木の実などが視界に入るはずです。

そのいずれもが、わたしたちが遠くから見たときに認識した山を構成している要素です。ピクニックでその山を訪れたことで、わたしたちは山についての認識をより豊かにすることができました。

このことをもう少し詳しく考えてみましょう。

わたしたちが遠くから山を見ているときには、山の全景を視界に収めることができましたが、山を構成する諸要素を視認することはできませんでした。山に近づくにつれ、山の全景は視界から去り、山を構成する諸要素が視界を占めることになりました。

つまり、わたしたちは常に、自分自身の「視界」というフレームを通じて世界と出会っており、その時点で得られる認識の範囲はそのフレームによって限界づけられているのです。その限定された認識の範囲を広げるために、わたしたちは、事象に近づいたり、事象から遠ざかったりして、より幅広い認識を手に入れます。

このようにしてわたしたちは世界を逍遙し、わたしたちが内面に有している世界の像をより完全なものに近づけようとします。

このような認識のあり方を、光学的な仕組みを用いて支援する装置がレンズです。

レンズを組み合わせた仕組みにより、わたしたちはこの場を動くことなしに、わたしたちの視界のフレームの大きさを疑似的に拡大したり縮小したりできます。それが望遠鏡・双眼鏡、顕微鏡などの装置です。とくに凸レンズと凹レンズを組み合わせたズームレンズなら、対象に焦点をあわせたまま寄ったり引いたりすることが可能です。

思考におけるレンジ操作

じつはわたしたちの思考も、同様の仕方で理念世界に向き合っているのです。ここでは数学的な要素について考えてみましょう。たとえば、わたしたちが特定の数値について考えを巡らすとき、思考のなかで扱える数の桁数には限りがあります。

3.14なら思考をそこに集中させることができますが、よほど特殊な才能の持ち主でないかぎり、3.141592653589793238462643383279502884197ではもてあますでしょう。122950000人という数字を見てもすぐにはピンときませんが、1億2千万人ならなんとかなります。0.0000000001F(ファラド)も同様で、できれば100pF(ピコファラド)としたいところです。

このように思考のステージに載せられるよう、操作対象にしたい数字のまとまりをクローズアップするような操作を、わたしたちは日常的に行っているわけです。この仕組みを応用して、非常に小さな数から非常に大きな数まで、幅広いレンジの数値を取り扱えるようにしたデータモデルが浮動小数点型です。

浮動小数点型は、ふたつの整数を組み合わせることで成り立っています。その一方は指数部と呼ばれ、もう一方を仮数部と呼ばれます。

指数部仮数部

仮数部は、思考のステージに載せた数字に相当するもので、操作の対象となる数値のまとまりです。整数型の学びで見たように、整数型は有限のビットの並びで表現されますから、そこに納める数値の桁数はそのサイズに依存します。これがさきほど考えた思考のステージや視界のフレームの大きさの制限に相当するものです。

指数部は、仮数部の数値が絶対値のなかでどのような大きさをもつのかを示すオフセット値を保持しています。ズームレンズに例えるなら、指数部はズーム機能に相当し、指数部の数値を調整することで、仮数部というファインダーのなかに被写体をちょうどよい大きさに納めるような役割をもっています。逆に考えれば、小さなファインダーに映った像が現実にはどのような大きさであるかを示す数値とも言えます。

ここで例として、地球の直径が既知であるとして、そこから地球の円周を求める計算を考えてみましょう。

浮動小数点型

浮動小数点型の仕組み:乗算を例に

地球の直径を赤道面の直径の平均値をとって12,756Kmとします。この数値から円周の長さを求めるには、円周率を乗じればよいわけです。

12,756 x 3.1415

このように、大きさがとても異なり、小数点を含んだ数値どうしを掛けたり割ったりすることは、日常生活のなかでも頻繁に起こります。このような操作を整数型で行うことは、現実的ではありません。そこで考案されたのが、浮動小数点型です。

では、上記の計算を浮動小数点の形式を用いて行う仕組みを見てみましょう。まず、この2つの数を、10進数のままで正規化してみましょう。浮動小数点型の正規化は、仮数部の桁数(ビット数)に、対象となる数値の有効桁数が最大になるように収める操作を言います。

ここでは、10進数4桁として考えてみましょう。

すべての数値の最上位が最上位桁に置かれるように桁をずらします。これが浮動小数点型における正規化という作業なります。

12,756 → 1275.6(小数点以下は切り捨てる)
3.1415 → 3141.5(小数点以下は切り捨てる)

このように頭を揃えてメモリーにセットすることで、用意したメモリーサイズにおける最大の有効桁数を確実に確保できるわけです。その際、ずらした数を指数部のための情報として記録しておきます。そうしないと、計算後に実際の桁に調整しなおす作業ができません。

12,756 → 1275:101
3.1415 → 3141:10-3

元の数値に戻したいときは、指数部の逆数を仮数部に乗じます。そうなることを確認しておきましょう。

さて、101、10-3は整数ではありませんから、これをそのまま指数部に保存することはできません。どうしたらよいか、生徒に問うてみてもよいかもしれません。そう、底の数値は常に一定なのですから、右肩の数値、指数を保管すればいいのです。だから指数部と呼ぶわけです。

 11275
-33141

考え方がわかりましたので、これを二進数でやってみましょう。ここでは、指数部も仮数部も8ビットの整数であるとします。10進数に比べると一桁の重みが5分の1ですから、8ビットだと円周率も3.1くらいまでしか表現できませんが、まずは小手調べ。これくらいでやってみましょう。

まず、この2種類の10進数を2進数の表記にします。一般的な方法は2で割り続ける方法です。出てきた余りを二進数の値として立てて、上位方向に桁を移していきます。

12,756 → 11 0001 1101 0100

円周率のほうは、整数部分と小数点以下の少数部分では変換方法が変わりますので、注意が必要です。各桁の重み付けが、小数部では2の累乗の逆数になるからです。

整数部の3は2+1ですから二進数では11です。小数点以下は、整数部とは逆に2をかけていき、整数部に繰り上がった値を二進数の値として立て、下位方向に桁を移していきます。変換の過程で無限小数になることがあり、その場合は小数点以下の計算は延々と終わらないので、適当な桁で切り上げます。

3.1415 → 11.0010 0100 001

この浮動小数点型モデルの仮数部では、2の補数形式が収まるように調整します。数値が正のときに最大桁数は7ビットとなるため、8ビット目の最上位桁には0を置きます。負数の場合はそのまま設定します。

地球の直径の場合は、小数点を上位方向に7桁ずらして、小数点以下を切り捨てて右詰で8ビットに納めます。最上位桁は0にします。桁をずらした指数は、27です。円周率は反対に、小数点を下位方向に5桁ずらします。指数は2-5です。

11 0001 1101 0100(12,75610) → 0110 0011:27(赤の下線部の桁数=7)
11(310).001 0010 0001(0.141510) → 0110 0100:2-5(赤の下線部の桁数=5)

桁をずらす操作は、整数の学びで少しだけ触れたシフト演算で行います。機械的なシフト動作を見てきた生徒たちにとって、それが数理的な演算に相当する事実は愉快な体験となるでしょう。

0000 01100110 0011
1111 10110110 0100

これで浮動小数点型のスタイルで、12,756の近似値と3.1415の近似値が表現できました。どの程度の近似値になるのか、10進数に戻してみましょう。

元の数:12,756 → 7ビット表現:12,672
元の数:3.1415 → 7ビット表現:3.125

おやまあ、思った以上に精度が失われていることがわかりました。でも、こんなところでしょう。これもよい学びです。

では、いよいよ地球の円周の長さを求めます。計算自体は簡単で、仮数部どうしを掛け合わせます。整数の掛け算です。8ビットどうしの掛け算の結果は最大16ビットになりますので、あらかじめ16ビット分のメモリーを用意しておきます。

  0110 0011
× 0110 0100
0010 0110 1010 1100

この結果が実際にどのような大きさの数になるのか、二つの指数によって求めます。乗算の場合は、指数同士を単純に足せばOKです。

7+(-5)=2

これがこの結果の指数です。この結果を仮数部8ビットの浮動小数点型とするには、さらに正規化を行います。7桁右にずらしたのですから、指数部に7を加えて9となります。

0000 10010100 1101

これを10進数に変換すると、以下の数字が出てきます。

39,424(Km)

おおよそ4万Km。これで浮動小数点の計算ができたわけです。精度に不満をもつ生徒が出てきたら、倍のビット数で同じことに取り組んでみてもいいでしょう。

このように、仮数部と指数部を組み合わせることにより、小数点を含むごく小さな値から莫大な大きさの数に至るまでをわずかなビット数のメモリーで表現できるようになります。すばらしいではありませんか。

同時にこの表現方法が人間の思考方法をモデルにしていることを、しっかり意識しておきましょう。

加算

では、加算について見てみましょう。加算の場合は、乗算の場合と違って、指数部が一致している場合を除き、仮数部どうしを直接足すことはできません。逆に言えば、指数部を一致させてから仮数部を足せば、加算ができるということになります。

地球の円周では、おおよその値を求める例でしたから概算値が求まればよかったのですが、多くの加算のケースでは有効桁数が問題になります。

正負表現を含む8ビットの整数で表現できる最大値は127ですから、10進数3桁にも満たないわけです。いくら指数部で幅広いレンジを指定できたとしても、この有効桁数では実用にならないでしょう。

0000 00000111 1111 12710

実際の実装では、単精度浮動小数点型でも仮数部23ビットの有効桁数が確保されています(IEEE 754)。これでも10進数の有効桁数が7桁に足りません。

0000 00000111 1111 1111 1111 1111 1111 8,388,60710

たとえばこの桁数で、神奈川県の人口9,219,618人を表現してみましょう。そのまま二進数にすると、1000 1100 1010 1110 0010 0010となり、仮数部の桁数を越えるので、指数部を操作して納めます。

1111 11110100 0110 0101 0111 0001 0001 9,219,61810

この人口が3,000人増えたとして、何人になるか計算します。

0000 10110101 1101 1100 0000 0000 0000 3,00010

ここで加算時にどちらの数に桁をあわせるかが問題になります。大きい数字を小さい数値の指数部にあわせようとすると、上位桁が失われてしまって数値の意味をなさなくなるため、小さい数値の指数を大きい数値のほうにあわせます。

 1111 11110100 0110 0101 0111 0001 0001 9,219,61810
1111 11110000 0000 0000 0101 1101 1100 3,00010
1111 11110100 0111 0101 1100 1110 1101 9,222,61810

計算ができています。

では、今度は先の人口が1人増えたとします。加算する浮動小数点型の数値1を用意します。

0001 01100100 0000 0000 0000 0000 0000 110

大きい数字の指数部にあわせます。

1111 11110000 0000 0000 0000 0000 00001 110

あっ、1が仮数部から押し出されて仮数部が0になってしまいました!

 1111 11110100 0110 0101 0111 0001 0001 9,219,61810
1111 11110000 0000 0000 0000 0000 0000 010

これでは、何度1を足しても、一向に数値は増えないことになります。このように、幅広いレンジの数値を扱える浮動小数点型ですが、有効桁数を意識しておかないととんでもないことが起こります。

これが整数型にはなかった難しさです。整数型なら、有効桁数が明快ですが、浮動小数点型はあいまいになりがちです。

整数型が使えるのであればできる限り整数型を使い、浮動小数点型を使わなければならない場合にこの問題を回避するには、仮数部の有効桁数を大きくします。IEEE 754の倍精度浮動小数点型では、仮数部が52ビットと大きな桁数が確保されます。10進数で15桁あまりの精度が得られます。

0000 0000
0 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 4,503,599,627,370,49510

すべての数を表現できるわけではない

指数部を導入したことにより、幅広いレンジの数値を取り扱える浮動小数点型ですが、ここまで見てきただけでも、有効桁数の問題や、10進数から2進数に変換する過程で発生する循環小数の切り捨て操作で発生する誤差を避けることができないことが理解されると思います。浮動小数点型は、あらゆる数値を表現できる夢の仕組みではないのです。

よく引き合いに出される例は、0.1+0.2の計算です。10進数から2進数への変換の過程で小数の循環が生じるので、打ち切った桁の範囲ですでに誤差が生じています。

 1111 11010110 1100 0.09960937510
1111 11100110 0110 0.1992187510
1111 11110100 1100 0.29687510

ご覧のように、答えは0.3にはなりません。これは有効桁数の問題ではなく、どんなに仮数部の桁数を増やしても循環は無限に続くので、この誤差を解消することはできないのです。

このように、浮動小数点型の表現する数値は、概数、あるいは近似値として扱うことが大切です。とくに、計算結果を厳密に比較して条件分岐するようなプログラムの場合は、よくよく注意する必要があります。

さら言えば、このことはコンピュータが扱う情報のすべてに言えることです。コンピュータは、有限のメモリー上に世界事象の表層だけを切り取ってつくった張りぼてを、さも真実であるかのように人間に差し出します。なぜ人々がそれを鵜呑みにしてしまうのかを、わたしたちは問うべきなのです。

2進化10進数型

人間が通常使っている10進表記と、コンピュータの内部形式である二進表記を行き来する際に、度々誤差が発生することを見てきました。この不都合を回避するために考案されたのが、2進化10進数型(BCD型)です。

これは、0~9までの値を4ビットの2進数表記で扱い、値が10を越えた際に上位の4ビットに桁上がりする仕組みで2進数に変換せずに10進数を扱えるようにした型です。この型で一貫して計算を行えば、上述のような誤差が発生しないので、お金の計算などの用途で広く使われています。

ただし、この形式だと、演算が複雑化し、時間もかかるという難点があります。また、表現できない数がある点では、通常の2進表記と変わりません。

おわりに

以上、浮動小数点型を見てきました。

このように、世界の事象をモデル化するために、その事象を構成するパラメータをセットにして扱うことで、より複雑な事象を扱うことができるようになります。単純な例で言えば、光の三原色を赤、緑、青の3つの輝度のセットで表現する例や、次項で取り上げる文字列型などの例があります。

プログラム言語におけるオブジェクトやリレーショナルデーターベースのレコードなども、この手法を拡大したものです。

浮動小数点型を足がかりに、メモリーのビット列を使って、様々な世界事象をどのように表現できるのかを、生徒たちと探求してみるとよいでしょう。そこから、それらのデータモデルを操作して目的の結果を導くためのアルゴリズムを探す探求も、自ずと生まれてくるでしょう。

ヴァルドルフICTカリキュラム-インデックス

コメント

タイトルとURLをコピーしました