如何为无符号整数类型指定可表示的最大值?

我想知道如何在下面的循环中初始化min,迭代计算一些结构的min和max长度。

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
}

使第一次通过比较,minLen >= n。


当前回答

注意:这个答案在go 1.17中被取代,其中包括e8eb1d8;例如:math包现在包含了用于math的常量。MaxUint,数学。MaxInt和math。minint。

快速总结:

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

背景:

我假设你知道,uint类型的大小与uint32或uint64相同,这取决于你所在的平台。通常,只有在没有接近最大值的风险时,才会使用这些类型的非大小版本,因为没有大小规范的版本可以使用“本机”类型,这取决于平台,往往更快。

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.

尽管如此,在某些情况下,了解自己在处理什么还是很有用的。

“math/bits”包包含uint的大小,以比特为单位。要确定最大值,将1移位那么多位,减去1。例如:(1 << bits.UintSize) - 1

注意,在计算uint的最大值时,你通常需要将它显式地放入一个uint(或更大的)变量中,否则编译器可能会失败,因为它将默认尝试将该计算分配到一个带符号的int中(很明显,它不适合),因此:

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

这是对你问题的直接回答,但还有一些相关的计算你可能会感兴趣。

根据规范,uint和int的大小总是相同的。

单位32或64位 Int与uint大小相同

所以我们也可以用这个常数来确定int的最大值,通过取相同的答案,然后除以2再减去1。ie:(1 << bits.UintSize) / 2 - 1

int的最小值,通过将1移动这么多位然后除以-2得到。ie:(1 << bits.UintSize) / -2

总而言之:

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

最小化:/ 2 - 1

薄荷糖:(1 << tbits .UintSize) / -2

完整示例(应与下面相同)

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

其他回答

我一直记得的方法是,取比特(int8是8位,int是 32位),除以8,你得到字节(int8将是一个字节,int 应该是四个字节)。

每个字节都是0xFF(有符号整数除外,在这种情况下是最有效的 字节将是0x7F)。结果如下:

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

使用数学包中定义的常量:

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
)

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

相关部分:

由于整数类型使用二补运算,因此可以推断 int和uint的最小/最大常量值。例如, const maxint = ^uint(0) const MinUint = 0 const MaxInt = int(MaxInt >> 1) const MinInt = - maxint - 1

根据@CarelZA的评论:

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

https://golang.org/ref/spec#Numeric_types为物理类型限制。

最大值是在math包中定义的,在你的例子中是math。MaxUint32

注意,因为没有溢出-超过最大值的增量会导致环绕。

解决这个问题的一种方法是从值本身获取起始点:

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