floatとdoubleの表現と精度

(2017-09-02)

IEEE754の仕様。記憶が薄れていたのでまとめておく。

float(32bit)は

  • 1bit: 符号
  • 8bit: 指数部(exponent)
  • 23bit: 仮数部(fraction)

double(64bit)は

  • 1bit: 符号
  • 11bit: 指数部
  • 52bit: 仮数部

で表される。

例えば-5.25(2進で-101.01)を表す場合、 -1.0101 * 2^2のように±1.xxxx * 2^nの形にして、負なら符号を1に、指数部を正(1~254or2046)にするため nに127or1023のバイアスを足した数を入れ、仮数部にはxxxxの部分の後ろに0を詰めたのをそのまま入れる。 したがって、-5.25のfloatは1 10000001 01010000000000000000000になる。

ただし、指数部が0のときは仮数部xxxxに対して0.xxxx * 2^-126or1022のように解釈し、 0や指数部で表すことができる数(2^-126or1022)より絶対値が小さい非正規化数を表すことができるようになっている。 また、Infinityはそれぞれ(255or2047,0)、NaNは(255or2047,0以外)で表す。

精度は仮数部の大きさに依存し、floatが10進でMath.log10(2 ** 23) = 6.92桁で、doubleがMath.log10(2 ** 52) = 15.65桁。JavaScriptの数値はdoubleなので 1234567890.12345691234567890.123457になり16~17桁目で値がおかしくなることが確認できる。

参考

IEEE 754 - Wikipedia

Double-precision floating-point format - Wikipedia