Detect signed int overflow in Go

d11wtq picture d11wtq · Nov 11, 2015 · Viewed 7.7k times · Source

I'm building a Lisp, and I want 32 bit integers to automatically switch to 64 bit integers if a computation would cause them to otherwise overflow. And likewise, for 64 bit overflows, switch to arbitrarily sized integers.

The problem I have is that I don't know what the "correct" way is to detect an integer overflow.

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

How can I efficiently check if c overflowed?

I have considered always converting to 64 bit values to do the calculation, then down-sizing again afterwards when possible, but that seems expensive and memory wasteful for something that is as primitive and core to the language as basic arithmetic.

Answer

peterSO picture peterSO · Nov 11, 2015

For example, to detect 32-bit integer overflow for addition,

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)
    }
}

Output:

integer overflow 2147483327 2147483327 0