[Go]mathパッケージの整数型の最大/最小値の定義

『入門Goプログラミング』のLESSON10にfloat64からint16に型変換する場合の話が出てくる。

Goの場合、32768のようなint16に収まらない値を型変換したら、エラーなどは発生せず、ラップアラウンドされて-32768になる。
もし、int16の範囲外の場合にエラーとしたい場合は、mathパッケージに定数として宣言されている各整数型の最大値/最小値によるチェックをすべきという話だった。具体的には以下のような感じ。

var v float64 = 32768
if v < math.MinInt8 || v > math.MaxInt8 {
    //なんらかのエラー処理
}

定数で宣言された最大値/最小値は、型付けのない定数となり、float64の値との比較が可能とのこと。※このあたりの理解が足りていない。


定数の宣言がどのようにされているのかが、ちょっと気になってみてみたら、以下のようになっていた。

// Integer limit values.
const (
	MaxInt8   = 1<<7 - 1
	MinInt8   = -1 << 7
	MaxInt16  = 1<<15 - 1
	MinInt16  = -1 << 15
	MaxInt32  = 1<<31 - 1
	MinInt32  = -1 << 31
	MaxInt64  = 1<<63 - 1
	MinInt64  = -1 << 63
	MaxUint8  = 1<<8 - 1
	MaxUint16 = 1<<16 - 1
	MaxUint32 = 1<<32 - 1
	MaxUint64 = 1<<64 - 1
)

例のごとく、あまり慣れ親しんでいない書き方で、最大値はなんとなくわかるけど、最小値の方がいまいちイメージできなかったので、以下の処理で確認してみた。

var v int8 = -1
for i := uint8(0); i < 8; i++ {
	fmt.Printf("%4d : %b\n", v<<i, uint8(v<<i))
}


//結果
  -1 : 11111111
  -2 : 11111110
  -4 : 11111100
  -8 : 11111000
 -16 : 11110000
 -32 : 11100000
 -64 : 11000000
-128 : 10000000

なるほど。1で埋まった状態でシフトしていくと最終的に符号ビットだけが1になり、最小値を表現できるということなんだ。

でも、それだったら以下のように書いてもいいような気もする。

var v2 int8 = 1
for i := uint8(0); i < 8; i++ {
	fmt.Printf("%4d : %b\n", v2<<i, uint8(v2<<i))
}

//結果
   1 : 1
   2 : 10
   4 : 100
   8 : 1000
  16 : 10000
  32 : 100000
  64 : 1000000
-128 : 10000000

8ビットの表現としてはどちらも同じだけど、なにかしらの工夫があって表現の仕方が異なるんだろうなとは思う。

最大値の表現が、その型の最大値を表現するビット数+1ビット目のみを立てて、そこから-1するという形になってておもしろい。


この記事が気に入ったらサポートをしてみませんか?