为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
慕田峪4524236 2021-11-22 15:26:26
我正在构建一个 Lisp,如果计算会导致它们溢出,我希望 32 位整数自动切换到 64 位整数。同样,对于 64 位溢出,切换到任意大小的整数。我的问题是我不知道检测整数溢出的“正确”方法是什么。a, b := 2147483647, 2147483647 c := a + b如何有效地检查 c 是否溢出?我考虑过总是转换为 64 位值来进行计算,然后在可能的情况下再次缩小规模,但这对于与基本算术一样原始和语言核心的东西来说似乎很昂贵并且浪费内存。
查看完整描述

2 回答

?
GCT1015

TA贡献1827条经验 获得超4个赞

例如,要检测加法的 32 位整数溢出,


package main


import (

    "errors"

    "fmt"

    "math"

)


var ErrOverflow = errors.New("integer overflow")


func Add32(left, right int32) (int32, error) {

    if right > 0 {

        if left > math.MaxInt32-right {

            return 0, ErrOverflow

        }

    } else {

        if left < math.MinInt32-right {

            return 0, ErrOverflow

        }

    }

    return left + right, nil

}

func main() {

    var a, b int32 = 2147483327, 2147483327

    c, err := Add32(a, b)

    if err != nil {

        // handle overflow

        fmt.Println(err, a, b, c)

    }

}

输出:


integer overflow 2147483327 2147483327 0


查看完整回答
反对 回复 2021-11-22
?
慕姐8265434

TA贡献1813条经验 获得超2个赞

对于 32 位整数,标准方法如您所说,转换为 64 位,然后再次减小大小 [1]:


package main


func add32(x, y int32) (int32, int32) {

   sum64 := int64(x) + int64(y)

   return x + y, int32(sum64 >> 31)

}


func main() {

   {

      s, c := add32(2147483646, 1)

      println(s == 2147483647, c == 0)

   }

   {

      s, c := add32(2147483647, 1)

      println(s == -2147483648, c == 1)

   }

}

但是,如果您不喜欢那样,可以使用一些位操作 [2]:


func add32(x, y int32) (int32, int32) {

   sum := x + y

   return sum, x & y | (x | y) &^ sum >> 30

}

https://github.com/golang/go/blob/go1.16.3/src/math/bits/bits.go#L368-L373

https://github.com/golang/go/blob/go1.16.3/src/math/bits/bits.go#L380-L387


查看完整回答
反对 回复 2021-11-22
  • 2 回答
  • 0 关注
  • 163 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信