パスワードを忘れた? アカウント作成
13775181 journal
日記

route127の日記: 高幡不動小数 2

日記 by route127

100.003の話を馬鹿発見器で見てる時は「そりゃそうだろ」みたいな感じで読み流してしまったが改めてスラドでこの話題について読んでいて0.1の内部表現を2の冪乗で書き下してみたくなって(3行くらいの)ワンライナーを書いた。

perl -e "$e = join '', reverse split '', unpack(qq/b32/, pack("f", shift @ARGV));$e=~/(?<sign>[01])(?<exp>[01]{8})(?<frac>[01]{23})/;print qq/$e\n$+{sign} $+{frac} $+{exp}\n/;$exp=eval('0b'. $+{exp})-127;print qq/ 2^$exp\n/;@frac=split('',$+{frac});grep{print qq/+ 2^/, -eval($_+1-$exp), qq/\n/}grep{$frac[$_]==1}0..22;"

1行目が2進数32bitベタ書き、2行目に符号部(1bit)、仮数部(23bit)、指数部(8bit)の分かち書き、それ以降で2の冪乗での書き下しを表示する。
これにコマンドライン引数として0.1を以下のように与えると

perl -e "$e = join '', reverse split '', unpack(qq/b32/, pack("f", shift @ARGV));$e=~/(?<sign>[01])(?<exp>[01]{8})(?<frac>[01]{23})/;print qq/$e\n$+{sign} $+{frac} $+{exp}\n/;$exp=eval('0b'. $+{exp})-127;print qq/ 2^$exp\n/;@frac=split('',$+{frac});grep{print qq/+ 2^/, -eval($_+1-$exp), qq/\n/}grep{$frac[$_]==1}0..22;" 0.1

以下の印字が得られる。

00111101110011001100110011001101
0 10011001100110011001101 01111011
    2^-4
+ 2^-5
+ 2^-8
+ 2^-9
+ 2^-12
+ 2^-13
+ 2^-16
+ 2^-17
+ 2^-20
+ 2^-21
+ 2^-24
+ 2^-25
+ 2^-27

これで色々実験すると128.1と127.1もその差は1でなかったりする。
(7.629394531e-6位違う。)

ところでこの辺の数値計算の話は学生時代に電子計算機概論で習ったのだったが教科書引っ張り出して当該頁を見てみるとIEEE 754には触れておらず、内部表現も、符号(1bit)、指数部(7bit)、仮数部(24bit)とIEEE754単精度(符号(1bit)、指数部(8bit)、仮数部(23bit))と異なっていた。
教科書の初版年見たら1987年だったのでIEEE 754-1985制定後ではあるが普及はまだしてなかったのか。
COBOLGS/M形式なのか?
IBMのWindows向けCOBOLのマニュアル見てたらCOMP-1形式はIEEE単精度らしいが。
IEEEの方も隠れビットとかあるしこの辺歴史的な流れがありそうだけど調べ切れなかった。

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
typodupeerror

身近な人の偉大さは半減する -- あるアレゲ人

読み込み中...