LoginSignup
1
1

0.1のfloat表現から0.1を算出する

Last updated at Posted at 2023-07-10

手元のCコンパイラで 0.1 を float で表現すると(IEEE754の32bitだと)
3DCCCCCD
すなわち
00111101110011001100110011001101
になるんですが、逆に、このビットパターンから0.1に戻す計算をしてみます。

符号部

0 0111101110011001100110011001101
符号部がゼロなのでプラスです。

指数部

以下の太字の部分です。
0 01111011 10011001100110011001101
01111011は10進数で123で、IEEE754の規格により 127 をゼロとします。
123-127=-4
なので、指数部の意味するところは $2^{-4}$ すなわち最終的に $1/16$ されます。

仮数部

以下の太字の部分です。
001111011 10011001100110011001101
IEEE754の規格によりこれは少数部なので1を加え
1.10011001100110011001101
と解釈します。

よく見ると1001が繰り返されている!ので、これを2進数の循環少数とみなして分数に変換します。$x$ とおき、循環する部分を太字にすると
$x$ = 1. 1 00 1
と表せて、循環部分は4桁なので16倍(2進数で10000倍)したものを用意します。
10000 $x$ = 11001. 1 00 1
2進数なのに注意。ここから
$x$ = 1. 1 00 1
を引くと、
$ 1111x = 11000$
$ x=\frac{11000}{1111} $
となります。

すなわち

指数部の$1/16$ を適用するため、分母を16倍(2進数なので0を4つ書き加える)します。

$ x=\frac{11000}{11110000} $

10進数で表すと
$ 11000 → 24 $
$ 11110000 → 240 $
すなわち
$ x=\frac{24}{240}=\frac{1}{10} $(10進数)
が導かれ、
00111101110011001100110011001101
というビットパターンが 0.1 であることを確認できました。めでたしめでたし。

おまけ

実際にこのビットパターンは 0.1 は表現できておらず、IEEE754に従って計算すると
0.100000001490116119384765625
となります。2進数の少数で $ \frac{1}{10} $ という値は表現できません。
今回は、例えるなら 0.3333334 という値を見て $ \frac{1}{3} $ を導いた、という話でした。

おまけ2

元々のビットパターンは手元のgccでコンパイルしてメモリの中身を取り出したものです。仮数部は切り捨てではなく切り上げするロジックになっているらしく、0.1より大きな値になっています。

1
1
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1