route127の日記: 高幡不動小数 2
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制定後ではあるが普及はまだしてなかったのか。
COBOLのGS/M形式なのか?
IBMのWindows向けCOBOLのマニュアル見てたらCOMP-1形式はIEEE単精度らしいが。
IEEEの方も隠れビットとかあるしこの辺歴史的な流れがありそうだけど調べ切れなかった。
10進型なら10000回よりは頑張る? (スコア:1)
機械翻訳にしてはよくできてるような気はしますが、それは私に理解できるかどうかとは関係ありません。
# さっぱりわからん
Re: (スコア:0)
何が違ってこうなっているのか、な
https://msdn.microsoft.com/ja-jp/library/xtba3z33(v=vs.120).aspx [microsoft.com]