ブログトップ 記事一覧 ログイン 無料ブログ開設

それはそれ。これはこれ。 このページをアンテナに追加 RSSフィード

2003 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2004 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2005 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2006 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 03 | 04 | 05 | 06 | 07 | 09 | 10 | 11 | 12 |
2012 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 11 | 12 |
2013 | 01 | 02 | 04 | 05 | 07 | 08 | 10 | 11 | 12 |
2014 | 02 | 03 | 07 | 08 | 09 | 10 | 11 | 12 |
2015 | 01 | 02 | 03 | 05 | 06 | 07 | 11 |
2016 | 07 |
2017 | 01 | 03 | 06 | 07 | 11 |
2018 | 05 |

2010-11-28(日)

[]2種類の浮動小数点形式 IEEE754とPDP 2種類の浮動小数点形式 IEEE754とPDPを含むブックマーク 2種類の浮動小数点形式 IEEE754とPDPのブックマークコメント

そこらへんの/usr/include/float.hにある浮動小数データの指数の最大値・最小値は、単精度だとこうなっている。

#define FLT_MIN_EXP     (-125)
#define FLT_MAX_EXP     128

何故正と負でこんなに差があるのかという解説*1


理由を一言で言うと、「Cの浮動小数モデルPDP浮動小数点形式に由来するが、実際に動いているCPUはIEEE754に従った浮動小数点形式を処理するから」である

どちらの形式も、単精度32ビットの内訳は、符号1ビット、指数部8ビット仮数23ビットであるが、指数部と仮数部の意味づけが異なる。

異なるのは、仮数部をどのように正規化するかで、IEEE754では1以上2未満にするが、PDPだと0.5以上1未満になる。実際の仮数表現では最上位の1のビットを省略するところは同じなので、有効数値桁はどちらも23ビット全体。他にも指数部の下駄がIEEE754だと127、PDPは128と異なるが今回の話とは関係ない。


Cの規格書の「5.2.4.2.2 Characteristics of floating types <float.h>」をみると、仮数部は0.5以上1未満になることがわかる。浮動小数点数を仮数部と指数部に分解する関数frexpで得られる仮数部も実際にその範囲になっている。つまり、CはPDP型の浮動小数点形式をベースにしている。UnixPDP上で誕生したという経緯があり、過去からの互換性を守るためであろう。


本題に戻って、実際にIEEE754で使える仮数部は00000000は±0か非正規化数、11111111は±∞か非数なので、00000001から11111110であり、下駄が127なので-126から+127になる。仮数部1で指数が-126〜+127というのを、仮数部0.5にすると指数は-125〜+128になり、冒頭の結果となる。

*1:某Q&Aサイトでした回答の再構成

トラックバック - http://d.hatena.ne.jp/otn/20101128

2010-11-08(月)

[] Rubyでcall by nameっぽいこと  Rubyでcall by nameっぽいことを含むブックマーク  Rubyでcall by nameっぽいことのブックマークコメント

Algol60の引数機構であるcall by nameは今ではすっかり廃れて若い人には知られていないと思われるが、一言で言うと「クロージャ引数に渡す」ということで、クロージャの表記が非常にコンパクト。変数や式がそのままクロージャになる。


Algol60のサンプルプログラム*1

VALUE指定のfromとtoがcall by valueで、それ以外のsumとvarとexprの引数がcall by name

BEGIN
  INTEGER m,n;
  PROCEDURE sub(sum, var, expr, from, to);
  VALUE from, to;
  INTEGER sum, var, expr, from, to;
  BEGIN
    sum := 0;
    FOR var := from STEP 1 UNTIL to DO sum := sum + expr;
  END;

  sub(m, n, n*n, 1, 10);
  print(m);
END

少し解説すると、subでsumに代入すると実引数であるmへの代入となる。varへの代入も同じくnへの代入となる。これだけならcall by referenceでも同じだ。違うのは、exprを評価すると、その時点で呼び出し側環境でn*nを評価してその結果を値とする。つまりn*nがクロージャとしてsubにexprという名前で渡ったことになる。


対応するRubyプログラム

call by name の代わりに、値をセットするクロージャと値をゲットするクロージャのペアを渡す。式に対しての値のセットはエラーにする。

def sub(setsum,getsum,setvar,getvar,setexpr,getexpr,from,to)
  setsum[0]
  for i in from..to
    setvar[i]
    setsum[ getsum[] + getexpr[] ]
  end
end

m=nil
n=nil
sub( lambda{|x| m=x}, lambda{m}, lambda{|x| n=x}, lambda{n},
     lambda{raise "bad use"}, lambda{ n*n }, 1, 10 )

puts m

うーん、これは手で書く気がしない。

*1:ENDの直前のセミコロンは不要

トラックバック - http://d.hatena.ne.jp/otn/20101108