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

我想知道如何在下面的循环中初始化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。


当前回答

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

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

我最初使用的代码取自@nmichaels在他的回答中使用的讨论线程。现在我用了一个稍微不同的计算方法。我附上了一些评论,以防其他人有和@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
)

最后两个步骤是有效的,因为正数和负数在2的补数算术中是如何表示的。关于数字类型的Go语言规范部分建议读者参考维基百科的相关文章。我还没有读过,但我确实从Charles Petzold的Code一书中了解了two的补码,这是一本非常容易理解的计算机和编码基础介绍。

我将上面的代码(减去大部分注释)放入一个小整数数学包中。

来自数学库: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)
}

注意:这个答案在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)
}

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

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

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