231

How does one specify the maximum value representable for an unsigned integer type?

I would like to know how to initialize min in the loop below that iteratively computes min and max lengths from some structs.

var minLen uint = ???
var maxLen uint = 0
for _, thing := range sliceOfThings {
  if minLen > thing.n { minLen = thing.n }
  if maxLen < thing.n { maxLen = thing.n }
}
if minLen > maxLen {
  // If there are no values, clamp min at 0 so that min <= max.
  minLen = 0
}

so that the first time through the comparison, minLen >= n.

Mike Samuel
  • 118,113
  • 30
  • 216
  • 245
  • 5
    take a look a this snippet `int(^uint(0) >> 1) // largest int` extracted from https://golang.org/doc/effective_go.html#printing – Victor Jun 03 '17 at 16:05

13 Answers13

323

https://groups.google.com/group/golang-nuts/msg/71c307e4d73024ce?pli=1

The germane part:

Since integer types use two's complement arithmetic, you can infer the min/max constant values for int and uint. For example,

const MaxUint = ^uint(0) 
const MinUint = 0 
const MaxInt = int(MaxUint >> 1) 
const MinInt = -MaxInt - 1

As per @CarelZA's comment:

uint8  : 0 to 255 
uint16 : 0 to 65535 
uint32 : 0 to 4294967295 
uint64 : 0 to 18446744073709551615 
int8   : -128 to 127 
int16  : -32768 to 32767 
int32  : -2147483648 to 2147483647 
int64  : -9223372036854775808 to 9223372036854775807
RickyA
  • 15,465
  • 5
  • 71
  • 95
nmichaels
  • 49,466
  • 12
  • 107
  • 135
  • 172
    Use the ones available in `math`: https://golang.org/pkg/math/#pkg-constants, you would want `math.MaxInt32` most likely. – Charles L. Jun 17 '16 at 21:25
  • 10
    Can someone explain exactly what ^uint(0) and ^uint(0) >> 1 do? – Arijoon Jun 29 '16 at 16:25
  • 27
    @Arijoon, ^ means invert bits in the expression so if: uint(0) == 0000...0000 (exactly 32 or 64 zero bits depending on build target architecture) then ^unit(0) == 1111...1111 which gives us the maximum value for the unsigned integer (all ones). Now when you are talking about signed integer then first (the most significant) bit is used to store sign therefore to the signed int maximum value - we need to shift all bits to the right which gives us ^uint(0) >> 1 == 0111...1111. Which gives the maximum positive integer. – ninjaboy May 09 '17 at 20:54
  • 5
    @CharlesL. what about just int type? – Imran Qadir Baksh - Baloch Jul 16 '18 at 13:43
  • 6
    I know it's been some time, but just in case someone comes here today and sees @user960567's Question-Comment: the `int` type is 32 bits long on a 32 bit system and 64 bits long on a 64 bit system. See [here](https://tour.golang.org/basics/11). – Christoph Float Dec 12 '19 at 14:26
  • Isn't this kind of brittle and nontransparent, and tied to the two's complement representation? Why not use `math.MaxInt16` etc.? – Jehan Jul 22 '20 at 21:22
  • @Jehan because topic about int, and int is either int32 or int 64 and can't be int16. – Rustam A. Aug 11 '20 at 15:39
  • @Jehan It is indeed tight to the two's complement representation. Luckily for us, Go only supports this representation since all others are really exotic by now. In the same vein, it requires Unicode as the only native character encoding, also for the good reason of establishing a single standard to be relied upon. – Roland Illig Jun 23 '21 at 15:47
  • Germane means relevant – Janac Meena Nov 08 '21 at 15:42
  • To get the max possible rune, without using "math" package, is using the same approach as for "int32" safe? – Eric Burel Mar 09 '23 at 12:49
92

https://golang.org/ref/spec#Numeric_types for physical type limits.

The max values are defined in the math package so in your case: math.MaxUint32

Watch out as there is no overflow - incrementing past max causes wraparound.

Claire Nielsen
  • 1,881
  • 1
  • 14
  • 31
Deleted
  • 4,804
  • 1
  • 22
  • 17
  • 4
    Thanks. I'm actually using `uint`, not `uint32`. The `len` and `cap` use `int` not `int32` so I want to use something that matches the size of those on all architectures. `math/const.go` defines a bunch of `Max` but none for either `uint` or `int. – Mike Samuel Jul 29 '11 at 20:34
  • I'd change it to uint32 or unit64 then to make sure it's portable across architectures. I do that with everything religiously. I've been through years of hell porting C between architectures and I can say that "being explicit" will help considerably later on. – Deleted Jul 29 '11 at 20:38
  • 1
    Thanks. My code has checks that `uint(len(...)) < thing.minLen` but I don't know whether `uint64(int)` is and will remain defined behavior. – Mike Samuel Jul 29 '11 at 20:50
  • 1
    If you don't know then read the spec linked above...specifically http://golang.org/doc/go_spec.html#Conversions. There's a careful definition of "conversions between numeric types". – Anschel Schaffer-Cohen Jul 31 '11 at 15:55
76

I would use math package for getting the maximal and minimal values for integers:

package main

import (
    "fmt"
    "math"
)

func main() {
    // integer max
    fmt.Printf("max int64   = %+v\n", math.MaxInt64)
    fmt.Printf("max int32   = %+v\n", math.MaxInt32)
    fmt.Printf("max int16   = %+v\n", math.MaxInt16)

    // integer min
    fmt.Printf("min int64   = %+v\n", math.MinInt64)
    fmt.Printf("min int32   = %+v\n", math.MinInt32)

    fmt.Printf("max float64 = %+v\n", math.MaxFloat64)
    fmt.Printf("max float32 = %+v\n", math.MaxFloat32)

    // etc you can see more int the `math`package
}

Output:

max int64   = 9223372036854775807
max int32   = 2147483647
max int16   = 32767
min int64   = -9223372036854775808
min int32   = -2147483648
max float64 = 1.7976931348623157e+308
max float32 = 3.4028234663852886e+38
ggorlen
  • 44,755
  • 7
  • 76
  • 106
Gujarat Santana
  • 9,854
  • 17
  • 53
  • 75
  • 3
    This code does not work. The two `int64`'s overflow int, which is what happens if you do not explicitly type constants prior to string interpolation. Use `int64(math.MaxInt64)` instead, see https://stackoverflow.com/questions/16474594/how-can-i-print-out-an-constant-uint64-in-go-using-fmt – domoarigato Dec 29 '17 at 21:40
  • 3
    But otherwise, is a better answer than the accepted one. :) – domoarigato Dec 29 '17 at 21:41
  • what happens if you use int64 on a machine with 32-bit word size? in C, the compiler decides the INT_MIN – segue_segway Aug 03 '19 at 19:14
24

note: this answer is superseded as of go 1.17, which included e8eb1d8; ie: the math package now includes constants for math.MaxUint, math.MaxInt, and math.MinInt.

Quick summary:

import "math/bits"
const (
    MaxUint uint = (1 << bits.UintSize) - 1
    MaxInt int = (1 << bits.UintSize) / 2 - 1
    MinInt int = (1 << bits.UintSize) / -2
)

Background:

As I presume you know, the uint type is the same size as either uint32 or uint64, depending on the platform you're on. Usually, one would use the unsized version of these only when there is no risk of coming close to the maximum value, as the version without a size specification can use the "native" type, depending on platform, which tends to be faster.

Note that it tends to be "faster" because using a non-native type sometimes requires additional math and bounds-checking to be performed by the processor, in order to emulate the larger or smaller integer. With that in mind, be aware that the performance of the processor (or compiler's optimised code) is almost always going to be better than adding your own bounds-checking code, so if there is any risk of it coming into play, it may make sense to simply use the fixed-size version, and let the optimised emulation handle any fallout from that.

With that having been said, there are still some situations where it is useful to know what you're working with.

The package "math/bits" contains the size of uint, in bits. To determine the maximum value, shift 1 by that many bits, minus 1. ie: (1 << bits.UintSize) - 1

Note that when calculating the maximum value of uint, you'll generally need to put it explicitly into a uint (or larger) variable, otherwise the compiler may fail, as it will default to attempting to assign that calculation into a signed int (where, as should be obvious, it would not fit), so:

const MaxUint uint = (1 << bits.UintSize) - 1

That's the direct answer to your question, but there are also a couple of related calculations you may be interested in.

According to the spec, uint and int are always the same size.

uint either 32 or 64 bits

int same size as uint

So we can also use this constant to determine the maximum value of int, by taking that same answer and dividing by 2 then subtracting 1. ie: (1 << bits.UintSize) / 2 - 1

And the minimum value of int, by shifting 1 by that many bits and dividing the result by -2. ie: (1 << bits.UintSize) / -2

In summary:

MaxUint: (1 << bits.UintSize) - 1

MaxInt: (1 << bits.UintSize) / 2 - 1

MinInt: (1 << bits.UintSize) / -2

full example (should be the same as below)

package main

import "fmt"
import "math"
import "math/bits"

func main() {
    var mi32 int64 = math.MinInt32
    var mi64 int64 = math.MinInt64
    
    var i32 uint64 = math.MaxInt32
    var ui32 uint64 = math.MaxUint32
    var i64 uint64 = math.MaxInt64
    var ui64 uint64 = math.MaxUint64
    var ui uint64 = (1 << bits.UintSize) - 1
    var i uint64 = (1 << bits.UintSize) / 2 - 1
    var mi int64 = (1 << bits.UintSize) / -2
    
    fmt.Printf(" MinInt32: %d\n", mi32)
    fmt.Printf(" MaxInt32:  %d\n", i32)
    fmt.Printf("MaxUint32:  %d\n", ui32)
    fmt.Printf(" MinInt64: %d\n", mi64)
    fmt.Printf(" MaxInt64:  %d\n", i64)
    fmt.Printf("MaxUint64:  %d\n", ui64)
    fmt.Printf("  MaxUint:  %d\n", ui)
    fmt.Printf("   MinInt: %d\n", mi)
    fmt.Printf("   MaxInt:  %d\n", i)
}
Will Palmer
  • 5,742
  • 1
  • 26
  • 33
  • Thanks. Your caveats about native numerics are well stated, and I was unaware of math/bits. – Mike Samuel Jan 30 '19 at 15:51
  • uint either 32 or 64 bits, int same size as uint. How can these be the same size if one has a sign and the other doesnt? – themiDdlest Jan 15 '20 at 22:43
  • They have the same bit-size, they don't have the same maximum/minimum values. One of the bits in that size *is* the sign bit. (the `/2` part is what removes that bit from consideration when calculating the size of min/max for int64) – Will Palmer Jan 18 '20 at 01:55
14

I originally used the code taken from the discussion thread that @nmichaels used in his answer. I now use a slightly different calculation. I've included some comments in case anyone else has the same query as @Arijoon

const (
    MinUint uint = 0                 // binary: all zeroes

    // Perform a bitwise NOT to change every bit from 0 to 1
    MaxUint      = ^MinUint          // binary: all ones

    // Shift the binary number to the right (i.e. divide by two)
    // to change the high bit to 0
    MaxInt       = int(MaxUint >> 1) // binary: all ones except high bit

    // Perform another bitwise NOT to change the high bit to 1 and
    // all other bits to 0
    MinInt       = ^MaxInt           // binary: all zeroes except high bit
)

The last two steps work because of how positive and negative numbers are represented in two's complement arithmetic. The Go language specification section on Numeric types refers the reader to the relevant Wikipedia article. I haven't read that, but I did learn about two's complement from the book Code by Charles Petzold, which is a very accessible intro to the fundamentals of computers and coding.

I put the code above (minus most of the comments) in to a little integer math package.

crantok
  • 1,333
  • 11
  • 18
10

Go-1.17 now defines MaxUint, MaxInt and MinInt constants in the math package.

package main

import "fmt"
import "math"

const maxUint = uint(math.MaxUint)

func main() {
    fmt.Println("Integer range on your system")

    // .Println("MaxUint:", math.MaxUint)  ERROR constant 18446744073709551615 overflows int
    fmt.Println("MaxUint:", maxUint)

    fmt.Println("MinInt:", math.MinInt)
    fmt.Println("MaxInt:", math.MaxInt)
}

The math package now defines three more constants: MaxUint, MaxInt and MinInt.
For 32-bit systems their values are 2^32 - 1, 2^31 - 1 and -2^31, respectively.
For 64-bit systems their values are 2^64 - 1, 2^63 - 1 and -2^63, respectively.

const (
    MaxInt    = 1<<(intSize-1) - 1   // New
    MinInt    = -1 << (intSize - 1)  // New
    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       // New
    MaxUint8  = 1<<8 - 1
    MaxUint16 = 1<<16 - 1
    MaxUint32 = 1<<32 - 1
    MaxUint64 = 1<<64 - 1
)

See also the Go source code: https://github.com/golang/go/blob/master/src/math/const.go#L39

mfink
  • 1,309
  • 23
  • 32
oHo
  • 51,447
  • 27
  • 165
  • 200
9

From math lib: https://github.com/golang/go/blob/master/src/math/const.go#L39

package main

import (
    "fmt"
    "math"
)

func main() {
    fmt.Printf("max int64: %d\n", math.MaxInt64)
}
g10guang
  • 4,647
  • 3
  • 28
  • 22
7

Use the constants defined in the math package:

const (
    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
    MaxUint8  = 1<<8 - 1
    MaxUint16 = 1<<16 - 1
    MaxUint32 = 1<<32 - 1
    MaxUint64 = 1<<64 - 1
)
M. Leonhard
  • 1,332
  • 1
  • 18
  • 20
3

One way to solve this problem is to get the starting points from the values themselves:

var minLen, maxLen uint
if len(sliceOfThings) > 0 {
  minLen = sliceOfThings[0].minLen
  maxLen = sliceOfThings[0].maxLen
  for _, thing := range sliceOfThings[1:] {
    if minLen > thing.minLen { minLen = thing.minLen }
    if maxLen < thing.maxLen { maxLen = thing.maxLen }
  }
}
SteveMcQwark
  • 2,169
  • 16
  • 9
2

Go 1.17 (Q4 2021) might help, with commit e8eb1d8, as noted by Go101:

Before Go 1.17, we can use the following trick to define MaxInt:

const MaxInt = int(^uint(0) >> 1)

Since Go 1.17, we can directly use math.MaxInt instead

That fixes issue 28538 reported by Silentd00m, reviewed with CL 247058.

Since we have int8 to int64 min max and uint8 to uint64 max constants, we should probably have some for the word size types too.

Tests are illustrating how this works:

    if v := int(MaxInt); v+1 != MinInt {
        t.Errorf("MaxInt should wrap around to MinInt: %d", v+1)
    }
    if v := int8(MaxInt8); v+1 != MinInt8 {
        t.Errorf("MaxInt8 should wrap around to MinInt8: %d", v+1)
    }
    if v := int16(MaxInt16); v+1 != MinInt16 {
        t.Errorf("MaxInt16 should wrap around to MinInt16: %d", v+1)
    }
    if v := int32(MaxInt32); v+1 != MinInt32 {
        t.Errorf("MaxInt32 should wrap around to MinInt32: %d", v+1)
    }
    if v := int64(MaxInt64); v+1 != MinInt64 {
        t.Errorf("MaxInt64 should wrap around to MinInt64: %d", v+1)
    }
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
0
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
MaxUint8  = 1<<8 - 1
MaxUint16 = 1<<16 - 1
MaxUint32 = 1<<32 - 1
MaxUint64 = 1<<64 - 1
Peace
  • 41
  • 2
0

The way I always remember it, is you take the bits (int8 is 8 bits, int is 32 bits), divide by 8 and you get the bytes (int8 would be one byte, int would be four bytes).

Each byte is 0xFF (except for signed integer, in which case most significant byte will be 0x7F). Here is result:

package main

func main() {
   {
      var n int8 = 0x7F
      println(n) // 127
   }
   {
      var n uint8 = 0xFF
      println(n) // 255
   }
   {
      var n int = 0x7FFF_FFFF
      println(n) // 2147483647
   }
   {
      var n uint = 0xFFFF_FFFF
      println(n) // 4294967295
   }
}
Zombo
  • 1
  • 62
  • 391
  • 407
-1

A lightweight package contains them (as well as other int types limits and some widely used integer functions):

import (
    "fmt"
    "<Full URL>/go-imath/ix"
    "<Full URL>/go-imath/ux"
)
...
fmt.Println(ix.Minimal) // Output: -2147483648 (32-bit) or -9223372036854775808 (64-bit)
fmt.Println(ix.Maximal) // Output: 2147483647 or 9223372036854775807
fmt.Println(ux.Minimal) // Output: 0
fmt.Println(ux.Maximal) // Output: 4294967295 or 18446744073709551615
LoveRick
  • 85
  • 3