LoginSignup
4
2

More than 5 years have passed since last update.

IEEE754 の微妙な数

Last updated at Posted at 2014-08-10

±0.0, ±Inf, NaN

ソースプログラム

    program float2
      implicit none
      real :: xp, xm, yp, ym, zp, zm 
      integer :: k
      !
      ! +0.0, -0.0 Minus Zero
      !
      xp = +0.0
      xm = -0.0
      print *, xp, xm
      print *, log(cmplx(2.0, xp)), log(cmplx(2.0, xm))
      print *
      !
      ! +Inf, -Inf
      !
      yp = 1.0 / xp
      ym = 1.0 / xm
      print *, yp, ym
      print *, atan(yp), atan(ym)
      print *
      !
      ! NaN
      !
      zm = sqrt(-1.0)
      k = transfer(zm, k)
      k = iand(k, b'01111111111111111111111111111111')
      zp = transfer(k, zp)
      print *, zp, zm
      print '(2b33.32)', zp, zm
      print *
      !
      ! +NaN, -NaN ???
      !
      print *, sign(1.0, zp), sign(1.0, zm)
      !
    end program float2

実行結果

  0.0000000E+00 -0.0000000E+00
 (0.6931472,0.0000000E+00) (0.6931472,-0.0000000E+00)
 
       Infinity      -Infinity
   1.570796      -1.570796
 
            NaN            NaN
 01111111110000000000000000000000 11111111110000000000000000000000
 
   1.000000      -1.000000
続行するには何かキーを押してください . . .

説明

±Zero

IEEE754 の数の体系には +0.0 と -0.0 の二つのゼロがあります。これを冗長でナンセンスとみる向きもありますが、例えば多価複素関数のリーマン面のカットラインの前後を区別するなどの目的で必要だという向きもあります。ここでは複素対数関数で虚部の正負が結果に反映されるのを見ています。

±Inf(Infinity)

IEEE754 以前はゼロでの除算は、"division by zero" の割り込みによるプログラムの強制終了を引き起こしていましたが、IEEE754では数の体系の中に ±Inf が導入されおり、結果を ±Inf のいずれかとして計算は続行されれます。ここでは Arctan(+Inf) は $\pi/2$ を、Arctan(-Inf) は $-\pi/2$ を返すことを見ています。

NaN (Not A Number)

IEEE754 以前は sqrt(-1.0) のような定義域を外れた演算は、"domain error" の割り込みによるプログラムの強制終了を引き起こしていましたが、IEEE754 では NaN という要素が数の体系の中に導入されており、結果を NaN として計算が続行されます。NaN とそれ以外の数との演算はすべて NaN と定義されています。したがって一度NaN が発生するとそれ以降の結果は皆 NaN に覆われてしまいます。(なお引数を複素数で与えれば関数 sqrt は複素数(0.0,1.0)を返します。)

しかし、奇妙なことに Intel Fortran の Sign 関数を用いると、NaN の符号ビットが読み取られ、結果が普通の数になりえます。これが Intel Fortran だけの奇行なのか、Fortran の規格によるものか、IEEE754 の規格によるものか、今のところよく分かりません。

なお NaN は定義よりビット列としては一意ではなくて沢山あります。符号ビット的に正負分同数ありますが、NaN そのものには符号はありません。

Intel Fortranでの注意

±0.0を使用するにはオプション指定が必要です
float2.png

IEEE754 様模型

6bits => 1bit:符号、2bits:指数部(2^0,2^1)、3bits:仮数部(1/2,1/4,1/8)

ビット表現

000 001 010 011 100 101 110 111
000 +0.000 +1.000 +2.000 +Inf -0.000 -1.000 -2.000 -Inf
001 +0.125 +1.125 +2.250 NaN -0.125 -1.125 -2.250 NaN
010 +0.250 +1.250 +2.500 NaN -0.250 -1.250 -2.500 NaN
011 +0.375 +1.375 +2.750 NaN -0.375 -1.375 -2.750 NaN
100 +0.500 +1.500 +3.000 NaN -0.500 -1.500 -3.000 NaN
101 +0.625 +1.625 +3.250 NaN -0.625 -1.625 -3.250 NaN
110 +0.750 +1.750 +3.500 NaN -0.750 -1.750 -3.500 NaN
111 +0.875 +1.875 +3.750 NaN -0.875 -1.875 -3.750 NaN

対応表

  |         上 位 ビ ッ ト         |
----------------------------
 下|+0.0       +inf |-0.0        -Inf |
 位| 非  正       | 非  正       |
 ビ| 正   規    N | 正   規    N |
 ッ| 規    化   a | 規    化   a |
 ト| 化     数  N | 化     数  N |
  | 数          | 数          |
----------------------------

数直線表示

-Inf     正規化数       非正規化数     正規化数       +Inf 
|-|-+-+-+-+-+-+-|+++++++|.......|.......|+++++++|-+-+-+-+-+-+-|-|
 -Huge=-3.750  -2.0     -1.0      0.0     +1.0    +2.0      +Huge=+3.75
4
2
0

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
4
2