Go中int类型的最大值

时间:2011-07-29 20:21:52

标签: numbers go

如何指定unsigned整数类型可表示的最大值?

我想知道如何在循环中初始化min,迭代计算某些结构的最小和最大长度。

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

11 个答案:

答案 0 :(得分:171)

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

密切关系部分:

  

由于整数类型使用二进制补码算法,因此可以推断出   intuint的最小/最大常量值。例如,

const MaxUint = ^uint(0) 
const MinUint = 0 
const MaxInt = int(MaxUint >> 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

答案 1 :(得分:61)

物理类型限制

https://golang.org/ref/spec#Numeric_types

最大值在数学包中定义,因此在您的情况下:math.MaxUint32

注意没有溢出 - 增加过去的最大值导致环绕。

答案 2 :(得分:16)

我会使用math包来获取最大值和最小值:

func printMinMaxValue() {
    // 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 flloat64= %+v\n", math.MaxFloat64)
    fmt.Printf("max float32= %+v\n", math.MaxFloat32)

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

输出:

max int64 = 9223372036854775807
max int32 = 2147483647
max int16 = 32767
min int64 = -9223372036854775808
min int32 = -2147483648
max flloat64= 1.7976931348623157e+308
max float32= 3.4028234663852886e+38

答案 3 :(得分:9)

我最初使用的是@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
)

最后两个步骤是有效的,因为在二进制补码算法中如何表示正数和负数。 Numeric types上的Go语言规范部分将读者引用到相关的Wikipedia article。我还没有读过这篇文章,但我确实从书Code by Charles Petzold中学到了两个补充,这是一本非常容易理解的计算机和编码基础知识。

我将上面的代码(减去大部分评论)放到了integer math package

答案 4 :(得分:4)

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

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

答案 5 :(得分:3)

快速摘要:

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

背景:

我想您知道,uint类型的大小与uint32uint64相同,这取决于您使用的平台。通常,只有在没有接近最大值的风险时才使用这些版本的未调整大小版本,因为没有大小规格的版本可以使用“本地”类型,具体取决于平台,这往往会更快。 / p>

请注意,它趋向于“更快”,因为使用非本机类型有时需要处理器执行额外的数学运算和边界检查,以模拟更大或更小的整数。考虑到这一点,请注意,处理器(或编译器的优化代码)的性能几乎总是比添加自己的边界检查代码更好,因此,如果有发挥作用的风险,它可能会使简单地使用固定大小的版本,并让优化的仿真处理由此产生的任何后果是合理的。

话虽如此,在某些情况下,了解您正在使用的工具还是很有用的。

math/bits”包包含uint的大小(以位为单位)。要确定最大值,请将1移去这么多的位,减去负1。即:(1 << bits.UintSize) - 1

请注意,在计算uint的最大值时,通常需要将其显式放入uint(或更大)变量中,否则编译器可能会失败,因为它将默认为尝试将计算结果分配给签名的int(显然不适合),所以:

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

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

根据specuintint的大小始终相同。

  

uint 32位或64位

     

int uint

大小相同

因此,我们也可以使用该常数来确定int的最大值,方法是采用相同的答案并除以2然后减去1。即:(1 << bits.UintSize) / 2 - 1

int的最小值,方法是将1移位那么多位,然后将结果除以-2。即:(1 << bits.UintSize) / -2

总结:

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

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

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

full example(应与以下相同)

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

答案 6 :(得分:2)

使用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
)

答案 7 :(得分:1)

我一直记得的方式是你取位(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
   }
}

答案 8 :(得分:0)

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

答案 9 :(得分: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

答案 10 :(得分:0)

Go 1.17(2021 年第 4 季度)可能会对 commit e8eb1d8 有所帮助,如 Go101 所述:

<块引用>

在 Go 1.17 之前,我们可以使用以下技巧来定义 MaxInt

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

从 Go 1.17 开始,我们可以直接使用 math.MaxInt 代替

修复了 issue 28538 报告的 Silentd00m,由 CL 247058 审核。

<块引用>

既然我们有 int8int64 min maxuint8uint64 max 常量,我们可能应该有还有一些用于字号类型。

Tests 说明了这是如何工作的:

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