背景
Goの独学を進める中で、ラップアラウンドなるものに出会いました。
こりゃ要注意だぞ...と思ったのでまとめます
※何かしら知見を得られたらその度に更新します
ラップアラウンドって何?
ざっくり
桁あふれ(オーバーフロー)の上位互換みたいなやつ。
最大値を超えたら、また最小値からスタートする、みたいな。
反対に最小値を下回ったら、最大値になっちゃう、みたいな。
(C言語でも同じことが発生するとかなんとか)
例えば
8ビットで数値を管理保持するint8の型を持つ変数aがあった場合
int8の範囲は-128~127じゃないですか。
すると、
現在 a = 127 だったとしたら、a++ をするとaの値が-128になります。
めっちゃ減っとるやんけ
逆にa = -128 の時に1を引くと127になります。
嘘だと思うならやってみてください
main.go
package main
import "fmt"
func main() {
var a int8 = 127
a++
fmt.Printf("ふつうは127+1=128のはず。でもこの結果は... %d\n", a)
a--
fmt.Printf("じゃあ-128-1は... %d\n", a)
}
それでよ
Goの場合、こういった現象が起きても特にエラーは発生しないらしく、ちょっと慎重に実装する必要がありそうです。
どうやって対策するの?
どうやら演算を行う前に、演算結果がラップアラウンドを起こさないか確認する必要があるみたいです。
なんてこったい。
int64だとこんな感じで事前チェックを入れるのかな...全然足りないので気が向いたら充実させます。
wrapArround.go
func wrapArround(a, b int64) bool {
if math.MaxInt64-a < b { // 足し算をして問題がないか?
return false
} else if a < math.MinInt64+b || b < math.MinInt64+a { // 引き算をして問題がないか?
return false
}
return true
}
気になっていること
もしや日付表現とかでも問題になったりする...?
参考図書