普段 uint32_t 型あたりで細々と暮らしている年寄です。Pharo様を学びながらも、ビット演算したりすることを考えると整数型のビット幅が気になって夜も眠れません。ホントか?そこで今回はSmallIntegerクラスについてチョイ調べて愕然。どうせint64_tだろ、などと高をくくっていたらば大間違い。
※Pharo関係記事の投稿順Indexは こちら
※今回の動作確認は、Windows11上のWSL2の上のUbuntu24.04LTS上のPharo 10.0.0を使用しています。
PharoのInteger
手元のPharo 10処理系のクラスのハイアラキーを拝見すると、IntegerクラスはNumberクラスのサブクラスであり、同格なところにFloatクラスとFractionクラスが存在しておるようです。分数を扱えるFractionクラスは「フツーの」C言語等には見当たりませぬが、Lisp系統などでは古くから使われていたのでビックリはいたしませぬ。今回注目しておりますIntegerクラスはさらにサブクラスで2分されとります。
-
- SmallInteger
- LargeInteger
お惚け老人的には、SmallIntegerが「ビット長固定の」いわゆる整数型、LargeIntegerが「ビット長が固定されていない」「真の整数に近づけたい気持ちのある」整数型と勝手に理解しましたぞ。
多倍長演算(メモリ以外に上限の制約がなければ「無限」多倍長演算?)をサポートしている言語もいろいろあり、モダンで強力なPharo様はそれも使えるのだと理解。
まずはSmallIntegerクラスのインスタンスの実例。さいしょは「1」ね。
さて本題はビット長が固定された上記のSmallIntegerのビット長です。SmallIntegerクラスを開いたSystem Browser画面を御覧じろ。
上記のSmallIntegerクラスのコメントの黄色マーカ部分を拝見するに
-
- ビット長は「イメージ」、つまりは仮想マシンの実装により異なる。当方は64bit環境。
- ビット長は31ビットまたは63ビット(おっと、この半端な感じは何?)
- 2の補数表現である(フツーでよかった。)
短絡的に64ビット環境だから、整数はCのint64_t型とコンパチでしょ、と思い込んでいたのですが、それは大間違いみたいです。
SmallIntegerクラスの上限と下限をPharo様に問いかけてみました。
下の方に被さっているのはWindowsの電卓プログラムです。いつもお世話になっております「プログラマー」モードね。PharoのSmallIntegerのmaxVal値は、電卓に入力すれば上記のように60ビット幅でしかありませぬ。まあ符号ビットがあるから実質61ビット幅ということかね。
なお、以下の電卓画面のように、64ビット幅のint64_tであれば以下が整数型の正の最大値です。
消えた3ビットは何かに使われているのか? いまいち腑に落ちませぬ。
LargeInteger
Pharo様の場合、自然と多倍長の整数演算が使えるのでお楽。これがC言語などでは、多倍長演算ライブラリなど呼び出して計算しないとならないのでメンドイです。過去回でCで多倍長演算してみた回が以下に。
ソフトな忘却力(26) GMP、The GNU MP Bignum Library
Pharo様では、+1するだけでSmallIntegerの上限を突き抜けていつの間にやらLargeIntegerに突入してます。こんな感じ。
なお、LargeIntegerは、LargePositiveIntegerとLargeNagativeIntegerの2つのサブクラスを従えてます。
上記の変数 a のビット長を調べると 61ビットらしいです。また64ビット以下じゃん。二乗を求めてみると、こんな感じ。
二乗したら121ビット幅だと。確かに。
Pharo自身に変数 a を16進数表示してもらいました。こんな感じ。
確かに61ビット幅みたい。
Smallだあ、Largeだあと気にせんでも計算はできるってことですかい?