Computing integer limits in Golang
Integer limits and Golang specification for constant expressions
How to calculate integer limit values?
Go provides all the maximum values for integer types inside the math package
const (
MaxInt = 1<<(intSize-1) - 1
MinInt = -1 << (intSize - 1)
MaxInt8 = 1<<7 - 1
MinInt8 = -1 << 7
MaxInt16 = 1<<15 - 1
MinInt16 = -1 << 15
MaxInt32 = 1<<31 - 1
MinInt32 = -1 << 31
MaxInt64 = 1<<63 - 1
MinInt64 = -1 << 63
MaxUint = 1<<intSize - 1
MaxUint8 = 1<<8 - 1
MaxUint16 = 1<<16 - 1
MaxUint32 = 1<<32 - 1
MaxUint64 = 1<<64 - 1
)
For instance, to obtain the biggest 64-bit unsigned integer, first we compute the number immediately greater than MaxUint64
with the expression 1<<64
(that is a 65-bit number), then we decrease it by 1.
So, I opened a Go playground to test a line that prints the biggest 64-bit unsigned integer fmt.Println(1<<64 - 1)
but the compiler complains about an overflow: ./prog.go:8:20: constant 18446744073709551615 overflows int Go build failed.
.
How is it possible that math uses a 65-bit integer and my code can’t compile, instead? Actually, the two expressions are quite different:
- math package assigns that expression to a const variable
- my code passes that expression as an argument to a function
Golang constant expressions
Golang specification clarifies this behaviour:
Constant expressions are always evaluated exactly; intermediate values and the constants themselves may require precision significantly larger than supported by any predeclared type in the language. The following are legal declarations:
const Huge = 1 << 100 // Huge == 1267650600228229401496703205376 (untyped integer constant)
const Four int8 = Huge >> 98 // Four == 4 (type int8)
Negate instead of bit-shift
The biggest 64-bit unsigned integer has all bits set to 1. Another way to obtain the biggest 64-bit unsigned integer is to negate a uint64 set to 0.
var maxUint64 uint64 = ^uint64(0)
Leave a comment