1より小さい数値を表現するには小数点が必要ですが、そうでなくても小数点が必要なことはあります。3.14とか42.195とか6.02×1023などです。
2つのやり方があります。
固定小数点で表現する方式。ビット列のどこかに小数点があると決めて計算します。
たとえば、簡単のために4ビットで考えて、右から1桁目と2桁目の間に小数点があるとすれば、
0111
は、11.1のことで、十進にすると3.5となります。
この表記法では(負の数は考えないとして)0から7.5までしか表現できません。4桁を整数に使うと0から15までを表現できることを考えると、小数点以下を表現できるようになった代わりに扱える数の範囲が狭くなっていることがわかります。
次の表は、4ビットのままで小数点をいろいろ動かして表現できる数を示したものです。小数点をどこに置いても4ビットなので16種類の数しか表現できないということを理解するのも大切です。
点の位置⇨ | 0000. | 000.0 | 00.00 | 0.000 |
---|---|---|---|---|
内部表現⇩ | 10進数 | |||
0000 | 0 | 0.0 | 0.00 | 0.000 |
0001 | 1 | 0.5 | 0.25 | 0.125 |
0010 | 2 | 1.0 | 0.50 | 0.250 |
0011 | 3 | 1.5 | 0.75 | 0.375 |
0100 | 4 | 2.0 | 1.00 | 0.500 |
0101 | 5 | 2.5 | 1.25 | 0.625 |
0110 | 6 | 3.0 | 1.50 | 0.750 |
0111 | 7 | 3.5 | 1.75 | 0.875 |
1000 | 8 | 4.0 | 2.00 | 1.000 |
1001 | 9 | 4.5 | 2.25 | 1.125 |
1010 | 10 | 5.0 | 2.50 | 1.250 |
1011 | 11 | 5.5 | 2.75 | 1.375 |
1100 | 12 | 6.0 | 3.00 | 1.500 |
1101 | 13 | 6.5 | 3.25 | 1.625 |
1110 | 14 | 7.0 | 3.50 | 1.750 |
1111 | 15 | 7.5 | 3.75 | 1.875 |
4桁(4ビット)ではあまり役に立つと思えませんが、桁数を多く取ればそれなりです。
32桁(32ビット)用意して負数を考えずに整数部16桁、小数部16桁にすれば、0から65 535.999 984 741 2まで表現できます。最小の値は0.000 015 258 789 062 5です。
64桁(64ビット)用意して負数を考えずに整数部32桁、小数部32桁にすれば、0から約4 294 967 295.999 999 999 767 169 356 346 13まで表現できます。最小の値は約0.000 000 000 232 830 643 653 87です。(さすがに一般の表計算では精度が足りません)
ただし、コンピュータで小数点のある数を扱う場合、浮動小数点数を使うのが主流です。
扱う数の大きさがそれほど大きくない場合は、固定小数点数が手軽に使えますが、6.02×1023などという大きい数値を扱うのは無理です。取り扱いに必要な桁数が大きくなりすぎて現実的でないからです。
6.02×1023 はアボガドロ定数といって有名な定数です。1023を使わないで書くと次のようになります。
602 000 000 000 000 000 000 000
このように本当は小数点がいらない数ですが整数で書くと、10進法でも24桁必要になります。これは2進法にすると79桁必要になります。現代よく普及しているコンピュータでは64ビットの浮動小数点数を使ってもっと大きな数まで計算しています。
このような大きい数を10進法で 6.02×1023 と書くのは、短く書きたいという他に精度の理由もあります。固定小数点数では602の後ろに0が21個あるので21桁にわたり0だと記憶します。でもここが本当に0かどうかは誰にもわからないので、覚えておいても役に立たない部分なのです。
この定数は12gの炭素の中にいくつの原子が入っているかというものですが、現在正しいだろうとされている最も精度の高い値はこれです。
6.02214129×1023 (2010年時点で確かだと思われている値)
つまりこの数値を書くときに24桁使うのは無駄だという事です。6.02214129の9桁と23の2桁、合わせて11桁と若干の約束(最後の2桁は10の肩に来る数値だよといった約束)があれば書けてしまいますから。
このような書き方は「指数表記」といいます。英語では「Scientific notation」です。表計算ソフトやコンピュータ出力では指数の小さな数字を出せないことが多いので、
6.02214129e23
と書くこともあります。
というわけで、浮動小数点数は単に小数部分を持つ数だけではなく、整数型の表現の限界を越える大きな数を扱う方法としても重要です。
もう少し指数の小さい数で説明しましょう。
4.6875×103
これは4.6875の小数点を3桁右に移動させた数のことで、4687.5のことです。
この時4.6875を 仮数部 3 を 指数部 10 を 基数 といいます。
(仮数部)×(基数)(指数部)
基数を2にし、仮数部も指数部も二進で表現するのが浮動小数点数です。
たとえば 3.5 は二進表現では 11.1 でしたが、
1.11×21
とします。基数の2だけ二進表現でないので変ですが、実際のデータでは2は書きません。
十進表現では10を掛けることで小数点が1桁右に移動しますが二進表現では2を掛けることで小数点が1桁右に移動しますから 21 が小数点が1桁右に移動することを指示しています。
さて、この仮数部と指数部を二進で表現すれば、みんな浮動小数点数なのですが、具体的にどうするかはさらにいくつかの種類があります。そこで、一番多く使われているIEEE754(アイトリプルイー、The Institute of Electrical and Electronics Engineers, Inc.)を説明します。
IEEE754は浮動小数点数の代表的な規格です。
正負の符号に1ビット、指数部に8ビット、仮数部に23ビット使います。
指数部(8) | 仮数部(23) | ||||||||||||||||||||||||||||||
0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
二進表現での精度(計算の細かさ)は23+1で24ビットです。十進表現での精度に直すと7桁の精度です。
4.6875はどうなるでしょうか。
4.6875 = 4 + 0.5 + 0.125 + 0.0625
ですから、二進表記は
100.1011
です。これを1.で始まる仮数部と指数部にします。
1.001011×210
指数部に127、二進では 1111111を足します
1111111
+ 10
10000001
仮数部は最初の1を省略し小数点以下だけを書く
指数部(8) | 仮数部(23) | ||||||||||||||||||||||||||||||
0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
-0.1はどうなるでしょうか。
まず、マイナスなので符号を1にします。
0.1は上にあるように循環小数になるのでした。
0.000110011001100…
です。これを1.で始まる仮数部と指数部にします。
1.10011001100×2-100
指数部に127、二進では 1111111を足します。指数部は -100 ですから引き算になります。
1111111
- 100
1111011
仮数部は最初の1を省略し小数点以下だけを書く
指数部(8) | 仮数部(23) | ||||||||||||||||||||||||||||||
1 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 1 |
循環小数なので入りきらないのですが、近い方を採用します。
最後の部分だけ注目しますと、
…1100 切り捨てた場合 …110011001100… 真の値 …1101 切り上げた場合
近いのは…1101 なので、切り上げています。
最近は浮動小数点数といえば64ビットを使うことが普通になりました。ビット数が多くなるだけでやり方は同じです。
正負の符号に1ビット、指数部に11ビット、仮数部に52ビット使います。
指数部(11) | 仮数部(52) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
二進表現での精度(計算の細かさ)は52+1で53ビットです。十進表現での精度に直すと15桁の精度です。
符号付きの整数で数値の範囲、あるいは精度は次の通りです。
バイト数 | 最小値 | 最大値 |
1 | -128 | 127 |
2 | -32768 | 32767 |
4 | -2147483648 | 2147483647 |
8 | -9223372036854775808 | 9223372036854775807 |
IEEE754の単精度(4バイト=32bit)、倍精度(8バイト=64bit)で表現できる数値の精度は次の通りです。
形式 | 有効数字の10 進表現 | 最大の正の数 | 最小の正の数(精度維持) | 最小の正の数 |
単精度 | 6-9桁 | 3.402... ×10+38 | 1.175... ×10-38 | 1.402... ×10-45 |
倍精度 | 15-17桁 | 1.797... ×10+308 | 2.225... ×10-308 | 4.940... ×10-324 |
有効数字6桁の精度とは長さを、1.23456km まで測る時の精度です。これは1234mと56cmのことですから、1kmの長さをcmの詳しさまで測ったということです。1kmから1cmまで6桁あるので有効数字6桁といいます。もしも123.456kmの場合は123kmと456mですからmの所まで測って6桁の精度ということになります。
科学技術の計算ではより精度の高い計算が必要な時は使用するビットを増やして計算をします。たとえば倍精度の2倍のビット数を使う4倍精度というものがあります。循環小数でも桁数が多ければより正確になるという考え方です。科学技術の分野ではこれで問題ありません。コンピュータの得意な2進法の中で計算しますから高速に計算できます。
2進法で浮動小数の計算をする場合、十進で正確に表現できる数も二進で循環小数になるという現象などで計算結果が微妙に変わってくる場合があります。また四捨五入をしたはずなのに結果が異なるということもあります。お金の計算で小数が入ってくる利息の計算などではこれではまずいので対策が必要です。
数値の内部表現を10進法を使う二進化十進法やBigDecimal(Javaの場合),割り算を分数にしたまま表現する方法などプログラム言語ごとに用意されていますので必要に応じて調べて使うようにします。