Go中int类型的最大值


132

如何指定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


2
看一下摘录int(^uint(0) >> 1) // largest intgolang.org/doc/effective_go.html#printing
Victor

Answers:


218

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

66
使用中提供的那些mathgolang.org/pkg/math/#pkg-constants,你想math.MaxInt32最有可能。
Charles L.

7
有人可以确切解释^ uint(0)和^ uint(0)>> 1做什么吗?
Arijoon

16
@Arijoon,^表示表达式中的反转位,因此如果:uint(0)== 0000 ... 0000(取决于构建目标体系结构,则为32或64个零位),则^ unit(0)== 1111 ... 1111这为我们提供了无符号整数(全1)的最大值。现在,当您谈论带符号的整数时,第一个(最高有效)位用于存储符号,因此为带符号的int最大值-我们需要将所有位向右移动,这使我们获得^ uint(0)>> 1 = = 0111 ... 1111。给出最大正整数。
ninjaboy'5

4
@CharlesL。只是int类型呢?
user960567

1
我知道已经有一段时间了,但是以防万一,今天有人来这里并看到@ user960567的问题注释:int类型在32位系统上为32位长,在64位系统上为64位。看这里
Christoph Harms-Ensink '19

73

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

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

当心,因为没有溢出-超过最大值会导致环绕。


2
谢谢。我实际上在使用uint,不是uint32。该lencap使用intint32那么我想用的东西,那些在所有的架构的大小相匹配。 为或int math/const.go定义了一堆,Max<type>但没有定义uint
Mike Samuel

我先将其更改为uint32或unit64,以确保其可跨体系结构移植。我认真地做所有事情。我经历了多年在架构之间移植C的经历,我可以说,“显式”将在以后提供很大帮助。
删除了

谢谢。我的代码有检查,uint(len(...)) < thing.minLen但我不知道是否uint64(int)是并且将保持定义的行为。
Mike Samuel

1
如果您不知道,请阅读上面链接的规范...特别是golang.org/doc/go_spec.html#Conversions。“数字类型之间的转换”有一个仔细的定义。
2011年

29

我将使用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
}

Ouput:

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

1
此代码不起作用。两者int64的溢出int,如果您没有在字符串插值之前显式键入常量,则会发生这种情况。int64(math.MaxInt64)改为使用,请参见stackoverflow.com/questions/16474594/…–
domoarigato

3
但除此之外,这是比公认的更好的答案。:)
domoarigato

如果在32位字长的计算机上使用int64,会发生什么情况?在C语言中,编译器决定INT_MIN
segue_segway

12

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

最后两个步骤之所以起作用,是因为在二进制补码算法中正数和负数的表示方式。关于数字类型的Go语言规范部分,向读者介绍了相关的Wikipedia文章。我还没有读过,但是我确实从Charles Petzold的《代码》一书中了解了二进制补,这是对计算机和编码基础知识的入门。

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


9

快速总结:

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,这取决于您所使用的平台。通常,只有在没有接近最大值的风险时才使用这些版本的未调整大小版本,因为没有大小规格的版本可以使用“本地”类型,具体取决于平台,这往往会更快。

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

说了这么多,在某些情况下了解您正在使用的内容很有用。

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

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

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

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

根据规格uintint大小始终相同。

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

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

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

谢谢。您对本机数字的警告已明确陈述,我不知道数学/位。
Mike Samuel

uint 32或64位,int与uint相同。如果一个有一个符号而另一个没有一个符号,它们怎么能一样大小?
themiDdlest

它们具有相同的位大小,没有相同的最大值/最小值。该大小的位之一符号位。(这/2部分是在计算int64的最小/最大大小时从考虑中除去该位的原因)
Will Palmer


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

1

轻量级软件包包含它们(以及其他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

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.