多倍長整数について考える。



 数(number)のリテラル表現としては,整数,単精度浮動小数点数,倍精度浮動小数点数,4倍精度浮動小数点数固定小数点数,N進数があります。

1234567890123456789012345678901234567890123456789
整数のリテラル表現。桁数に制限はありません。オブジェクトメモリがある限り,どんなに長い桁を有する整数も表現できる多倍長整数になります。
123.45
単精度浮動小数点数リテラル表現。
123.45d
倍精度浮動小数点数リテラル表現。
123.45q
4倍精度浮動小数点数リテラル表現。
1.2345e2
単精度浮動小数点数リテラル表現。基数部に指数部が累乗されます。
1.2345d2
倍精度浮動小数点数リテラル表現。基数部に指数部が累乗されます。
1.2345q2
4倍精度浮動小数点数リテラル表現。基数部に指数部が累乗されます。
1234.5s2
固定小数点数リテラル表現。1234.50sを表わします。少数部の桁を固定する必要がある会計処理などのビジネス系のプログラム開発に重宝します。
8r377
8進数のリテラル表現。255の整数を表わします。
16rFFFF
16進数のリテラル表現。65535の整数を表わします。

これによると、Smalltalkは標準で多倍長整数リテラルをサポートしているみたいで、変数は型とバイト制限がないらしい。

これを読んでいてふと思うのは、
0x1000000000000001(Smalltalkの16進数表記は違うが便宜上こっちの方がわかる。)
みたいなリテラルってどういう風に扱われるかってこと。
(開発環境ないので以下想像っていうことで)

普通、32bitCPUにのっている整数レジスタは32bitで
(知らないだけで64bitもあるかも知れないが…便宜上32bit整数レジスタで話を進める。)、
64bitの値をレジスタに乗せるときは最低でも2回のメモリ読み出しが必要となる。
バイト長が長くなればなるほどなおさら回数は増えるわけで、
メモリアクセスを少なくしたい俺にとっては、
そんなん使ってられるか!ってことになる。


また、(1)0x1000000000000001 - 0x01 のような演算はどうだろう?

この計算の場合、上位ワードは計算に影響されないので、
コンパイラで0x00000001 - 0x00000001(符号拡張)にでも変換されると思われる。つまり、2回メモリを読み出しに行けばよい。

さらに、(2)0xffefffffffffffff + 0xff はどうだろう?
(1)のときのように計算結果の上位ワードは変化ないが、
符号ビットの関係で上位ワードが必要となってくるはずだ。
また、0xffも符号拡張をして0xffefffffffffffffに桁あわせをしてやる必要がある。
つまり、0xffefffffffffffff + 0xffffffffffffffffになるはずだ。
ということは、4回メモリを読み出しに行くわけで。

まぁ、何がいいたいかというと、
オブジェクトメモリいっぱい、ひとつのリテラルで使用したときに、
SmalltalkのオブジェクトメモリはMB単位で確保するらしい。)
キャッシュには乗らないわ、リテラルひとつを呼び出すメモリアクセス回数が膨大になる状況をSmalltalkがどうやって回避してるのか知りたいなぁ。ってわけで

Smalltalkイディオム

Smalltalkイディオム

を読んでみたい。まぁ、回避してなかったらしょうがないけど。


そういえば、



Smalltalkは自分自身が走行しながら変遷をしていくプログラミング言語

という1文を読んで、大学時代で使ったこれを思い出した。

電子計算機 (情報工学入門シリーズ)

電子計算機 (情報工学入門シリーズ)

うーむ。なつかしい。