El valor máximo para un tipo int en Go
¿Cómo se especifica el valor máximo representable para un unsigned
tipo entero?
Me gustaría saber cómo inicializar min
el siguiente bucle que calcula de forma iterativa las longitudes mínima y máxima de algunas estructuras.
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
}
para que la primera vez a través de la comparación minLen >= n
,.
https://groups.google.com/group/golang-nuts/msg/71c307e4d73024ce?pli=1
La parte pertinente:
Dado que los tipos de números enteros utilizan aritmética en complemento a dos, puede inferir los valores constantes mínimo/máximo para
int
yuint
. Por ejemplo,const MaxUint = ^uint(0) const MinUint = 0 const MaxInt = int(MaxUint >> 1) const MinInt = -MaxInt - 1
Según el comentario de @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 para conocer los límites de tipo físico.
Los valores máximos se definen en el paquete matemático, por lo que en su caso: math.MaxUint32
Tenga cuidado, ya que no hay desbordamiento: incrementar más allá del máximo provoca un ajuste.
Usaría math
el paquete para obtener los valores máximos y mínimos de números enteros:
package main
import (
"fmt"
"math"
)
func main() {
// 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 float64 = %+v\n", math.MaxFloat64)
fmt.Printf("max float32 = %+v\n", math.MaxFloat32)
// etc you can see more int the `math`package
}
Producción:
max int64 = 9223372036854775807
max int32 = 2147483647
max int16 = 32767
min int64 = -9223372036854775808
min int32 = -2147483648
max float64 = 1.7976931348623157e+308
max float32 = 3.4028234663852886e+38
nota: esta respuesta queda reemplazada a partir de go 1.17 , que incluía e8eb1d8 ; es decir: el math
paquete ahora incluye constantes para math.MaxUint
, math.MaxInt
y math.MinInt
.
Sumario rápido:
import "math/bits"
const (
MaxUint uint = (1 << bits.UintSize) - 1
MaxInt int = (1 << bits.UintSize) / 2 - 1
MinInt int = (1 << bits.UintSize) / -2
)
Fondo:
Como supongo que sabes, el uint
tipo es del mismo tamaño que uint32
o uint64
, dependiendo de la plataforma en la que te encuentres. Por lo general, se usaría la versión sin tamaño de estos solo cuando no haya riesgo de acercarse al valor máximo, ya que la versión sin una especificación de tamaño puede usar el tipo "nativo", dependiendo de la plataforma, que tiende a ser más rápido.
Tenga en cuenta que tiende a ser "más rápido" porque el uso de un tipo no nativo a veces requiere que el procesador realice operaciones matemáticas y de verificación de límites adicionales para emular el entero más grande o más pequeño. Con esto en mente, tenga en cuenta que el rendimiento del procesador (o del código optimizado del compilador) casi siempre será mejor que agregar su propio código de verificación de límites, por lo que si existe algún riesgo de que entre en juego, puede hacer que Tiene sentido simplemente usar la versión de tamaño fijo y dejar que la emulación optimizada maneje cualquier consecuencia de eso.
Dicho esto, todavía hay algunas situaciones en las que es útil saber con qué estás trabajando.
El paquete " math/bits " contiene el tamaño de uint
, en bits. Para determinar el valor máximo, cambie 1
esa cantidad de bits, menos 1, es decir:(1 << bits.UintSize) - 1
Tenga en cuenta que al calcular el valor máximo de uint
, generalmente necesitará ponerlo explícitamente en una uint
variable (o mayor); de lo contrario, el compilador puede fallar, ya que de forma predeterminada intentará asignar ese cálculo en una variable firmada int
(donde, como debería sería obvio, no encajaría), entonces:
const MaxUint uint = (1 << bits.UintSize) - 1
Esa es la respuesta directa a su pregunta, pero también hay un par de cálculos relacionados que pueden interesarle.
Según las especificaciones , uint
siempre int
son del mismo tamaño.
uint
ya sea 32 o 64 bits
int
mismo tamaño queuint
Entonces también podemos usar esta constante para determinar el valor máximo de int
, tomando esa misma respuesta y dividiéndola por 2
luego restando 1
. es decir:(1 << bits.UintSize) / 2 - 1
Y el valor mínimo de int
, desplazando 1
esa cantidad de bits y dividiendo el resultado por -2
. es decir:(1 << bits.UintSize) / -2
En resumen:
MáxUint: (1 << bits.UintSize) - 1
MáxInt: (1 << bits.UintSize) / 2 - 1
MinInt: (1 << bits.UintSize) / -2
ejemplo completo (debe ser el mismo que se muestra a continuación)
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)
}