Island Life

< ここにごみを捨てないでください | Residual顛末 >

2015/05/12

指数表記

続けてkbkさんのところからネタをもらうけど

http://www.kt.rim.or.jp/~kbk/zakkicho/15/zakkicho1505b.html#D20150512-6

difference - 言語比較 > 10のべき数を表す記号 > D / E / *10^ - Qiita

D って FORTRAN 以外でも使ってた?

Common LispとSchemeにはDとEだけじゃなくてFもLもSもあるぞ。

1.0E1  ; デフォルトの精度 
1.0D1  ;  倍精度 (double-float)
1.0F1  ;  単精度 (single-float)
1.0L1  ;  長精度 (long-float)
1.0S1  ;  短精度 (short-float)

で、ちょっと落とし穴なのは、Common Lispの場合 eで使われるデフォルトの初期値が単精度なんだよね。 メモリが少なかったり倍精度演算が遅かったりした時代の名残りかもしれないけど、 倍精度で計算してるつもりで定数をeで書いといたらそこだけ単精度に丸められて微妙に誤差が、 みたいなことが。 (Schemeはデフォルトの精度は決められていない。Gaucheでは全てdouble floatにする。)

なので倍精度を確実にしたいならdを使うのが良い。

ところでCLのshort floatは仮数部13bit以上、指数部5bit以上と決められているので 画像フォーマットで使われるhalf float (仮数部11bit)だと微妙に足りない。 single floatとは別にshort floatを実装してた処理系ってあったのかなあ。 36bit/wordのマシンだと1wordに2つのshort floatが入るから、 そういうアーキテクチャで使われてたのかも。

Tags: CommonLisp, Scheme, Programming

Past comment(s)

g000001 (2015/05/12 22:44:55):

自分も今回調べてみて初めて知りましたが、任意精度のfloatを持つCLISPは、shortもsingleとは別に持つようです。 http://www.clisp.org/impnotes/num-concepts.html#float-comp

1.0E1
;=>  10.0

1.0D1
;=>  10.0d0

1.0F1
;=>  10.0

1.0L1
;=>  10.0L0

1.0S1
;=>  10.0s0

(eql 1.0f1 1.0s1)
;=>  NIL

ついでに36bitマシンについても面白そうなので調べてみましたが、Symbolicsのエミュレータでは、shortは、singleと同じ、longは、doubleと同じで、いまいち面白くない結果でした。 MIT Lispマシンの場合は、ieee 754とは別の形式を採用していて、 標準的に1.0のように指数マーカーが付かない表記で書くと、flonum / single-float / full-size-floatで仮数部31ビット指数部11ビットになり、 1.0s0のように指数マーカーSが付くと、small-float / short-floatとなり、仮数部17ビットで指数部8ビットだったようです。 http://bknr.net/static/lmman/fd-num.xml

1ワード(24bit)に収まるのでfixnum同様嬉しいというものはあったようですが、収まるのは1つだったようです。

Common Lispで例えるなら、doubleが標準だったような感じでしょうか。 Common Lispはieee 754と合せるということもあったとは思いますが、Lispマシンより精度が低い方に合せたというのが面白いと思いました。

また、36ビットマシンのPDP-10のMacLISPも眺めてみましたが、どうもflonumしかないようです。

shiro (2015/05/13 08:30:51):

ほうほう、CLISPの実装はあんまり見たことなかったです。32bit機でも即値で持てるのはメリットだろうけど、よっぽどカジュアルな用途以外は精度が違うのでいまいち使えなさそう&ネイティブな浮動小数点数型への変換のオーバヘッドはどうなるんだろ、という印象も受けますね。long floatを任意精度にするのはうまいな。

Post a comment

Name: