在 Go 中检测有符号整数溢出

我正在构建一个 Lisp,如果计算会导致它们溢出,我希望 32 位整数自动切换到 64 位整数。同样,对于 64 位溢出,切换到任意大小的整数。

我的问题是我不知道检测整数溢出的“正确”方法是什么。

a, b := 2147483647, 2147483647
c := a + b

如何有效地检查 c 是否溢出?

我考虑过总是转换为 64 位值来进行计算,然后在可能的情况下再次缩小规模,但这对于与基本算术一样原始和语言核心的东西来说似乎很昂贵并且浪费内存。


慕田峪4524236
浏览 164回答 2
2回答

GCT1015

例如,要检测加法的 32 位整数溢出,package mainimport (&nbsp; &nbsp; "errors"&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "math")var ErrOverflow = errors.New("integer overflow")func Add32(left, right int32) (int32, error) {&nbsp; &nbsp; if right > 0 {&nbsp; &nbsp; &nbsp; &nbsp; if left > math.MaxInt32-right {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return 0, ErrOverflow&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; if left < math.MinInt32-right {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return 0, ErrOverflow&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; return left + right, nil}func main() {&nbsp; &nbsp; var a, b int32 = 2147483327, 2147483327&nbsp; &nbsp; c, err := Add32(a, b)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; // handle overflow&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println(err, a, b, c)&nbsp; &nbsp; }}输出:integer overflow 2147483327 2147483327 0

慕姐8265434

对于 32 位整数,标准方法如您所说,转换为 64 位,然后再次减小大小 [1]:package mainfunc add32(x, y int32) (int32, int32) {&nbsp; &nbsp;sum64 := int64(x) + int64(y)&nbsp; &nbsp;return x + y, int32(sum64 >> 31)}func main() {&nbsp; &nbsp;{&nbsp; &nbsp; &nbsp; s, c := add32(2147483646, 1)&nbsp; &nbsp; &nbsp; println(s == 2147483647, c == 0)&nbsp; &nbsp;}&nbsp; &nbsp;{&nbsp; &nbsp; &nbsp; s, c := add32(2147483647, 1)&nbsp; &nbsp; &nbsp; println(s == -2147483648, c == 1)&nbsp; &nbsp;}}但是,如果您不喜欢那样,可以使用一些位操作 [2]:func add32(x, y int32) (int32, int32) {&nbsp; &nbsp;sum := x + y&nbsp; &nbsp;return sum, x & y | (x | y) &^ sum >> 30}https://github.com/golang/go/blob/go1.16.3/src/math/bits/bits.go#L368-L373https://github.com/golang/go/blob/go1.16.3/src/math/bits/bits.go#L380-L387
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go