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

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


当前回答

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

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

其他回答

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

一个轻量级包包含了它们(以及其他int类型的限制和一些广泛使用的整数函数):

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

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

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

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

Go-1.17现在在数学包中定义了MaxInt, MaxInt和MinInt常量。

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

测试上面的代码:https://play.golang.org/p/5R2iPasn6OZ 来自Go 1.17发布说明:https://golang.org/doc/go1.17#math

数学包现在又定义了三个常量:MaxInt、MaxInt和MinInt。 对于32位系统,它们的值分别是2^32 - 1,2 ^31 - 1和-2^31。 对于64位系统,它们的值分别是2^64 - 1,2 ^63 - 1和-2^63。

提交:https://github.com/golang/go/commit/e8eb1d82 文档:https://pkg.go.dev/math pkg-constants

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
)

参见Go源代码:https://github.com/golang/go/blob/master/src/math/const.go#L39

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