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.
Write a “C” function, int addOvf(int* result, int a, int b) If there is no overflow, the function places the resultant = sum a+b in “result” and returns 0. Otherwise it returns -1. The solution of casting to long and adding to find detecting the overflow is not allowed.
For efficiency, Golang does not check for overflow. In that legitimate design decision, Golang keeps the company of C, C++, and Java. While ignoring overflow is efficient and practical, equally legitimate reasons exist for protecting against incorrect results.
Overflow Detection – So overflow can be detected by checking Most Significant Bit(MSB) of two operands and answer. But Instead of using 3-bit Comparator Overflow can also be detected using 2 Bit Comparator just by checking Carry-in(C-in) and Carry-Out(C-out) from MSB's. Consider N-Bit Addition of 2's Complement number.
An integer overflow occurs when a value does not fit within its allocated memory space. This can occur for a variety of reasons, but an integer overflow should almost always be handled properly since they can cause unexpected or incorrect behavior and can pose serious security risks for a program.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With