web-dev-qa-db-fra.com

La valeur maximale pour un type int dans Go

Comment spécifier la valeur maximum représentable pour un type entier unsigned?

Je voudrais savoir comment initialiser min dans la boucle ci-dessous qui calcule de manière itérative les longueurs min et max de certaines structs.

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
}

de sorte que la première fois à travers la comparaison, minLen >= n.

101
Mike Samuel

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

La partie germane:

Comme les types entiers utilisent l’arithmétique des complément à deux, vous pouvez en déduire les valeurs constantes min/max pour int et uint. Par exemple,

const MaxUint = ^uint(0) 
const MinUint = 0 
const MaxInt = int(MaxUint >> 1) 
const MinInt = -MaxInt - 1

Selon le commentaire 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
186
nmichaels

https://golang.org/ref/spec#Numeric_types pour les limites de type physique.

Les valeurs maximales sont définies dans le package mathématique, donc dans votre cas: math.MaxUint32

Attention, il n'y a pas de dépassement de capacité - incrémentation des causes maximales au-delà des enveloppes.

65
Deleted

J'utiliserais le package math pour obtenir la valeur maximale et la valeur minimale:

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
18
Gujarat Santana

J'ai initialement utilisé le code tiré du fil de discussion utilisé par @nmichaels dans sa réponse. J'utilise maintenant un calcul légèrement différent. J'ai inclus des commentaires au cas où quelqu'un aurait la même requête que @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
)

Les deux dernières étapes fonctionnent en raison de la façon dont les nombres positifs et négatifs sont représentés dans l'arithmétique du complément à deux. La section de spécification de langue Go sur types numériques renvoie le lecteur au article Wikipedia correspondant. Je n'ai pas lu cela, mais le livre Code de Charles Petzold , qui m'a permis de découvrir le complément de deux, est une introduction très accessible aux notions de base de l'informatique et du codage.

Je mets le code ci-dessus (moins la plupart des commentaires) dans un peu paquet mathématique entier .

10
crantok

Une façon de résoudre ce problème est d’obtenir les points de départ des valeurs elles-mêmes:

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

Résumé rapide:

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

Contexte:

Comme vous le savez sans doute, le type uint a la même taille que uint32 ou uint64, selon la plate-forme sur laquelle vous vous trouvez. Habituellement, on utilise la version non dimensionnée de ceux-ci uniquement lorsqu'il n'y a aucun risque d'approcher de la valeur maximale, car la version sans spécification de taille peut utiliser le type "natif", en fonction de la plate-forme, ce qui a tendance à être plus rapide.

Notez qu'il a tendance à être "plus rapide" car l'utilisation d'un type non natif nécessite parfois que le processeur effectue une vérification mathématique et une vérification des limites supplémentaires, afin d'émuler le plus grand ou le plus petit entier. Dans cet esprit, sachez que les performances du processeur (ou du code optimisé du compilateur) seront presque toujours meilleures que l’ajout de votre propre code de vérification des limites. Par conséquent, s’il existe un risque qu’il entre en jeu, Il est donc logique d’utiliser simplement la version à taille fixe et de laisser l’émulation optimisée gérer les retombées de celle-ci.

Cela dit, il est toujours utile de savoir avec quoi vous travaillez.

Le paquetage " math/bits " contient la taille de uint, en bits. Pour déterminer la valeur maximale, déplacez 1 par autant de bits, moins 1. Par exemple: (1 << bits.UintSize) - 1

Notez que lorsque vous calculez la valeur maximale de uint, vous devrez généralement la définir explicitement dans une variable uint (ou supérieure), sinon le compilateur risque d’échouer car il essaiera par défaut de d'affecter ce calcul à un int signé (où, comme cela devrait être évident, il ne rentrerait pas), alors:

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

C'est la réponse directe à votre question, mais il y a aussi quelques calculs connexes qui pourraient vous intéresser.

Selon spec , uint et int ont toujours la même taille.

uint 32 ou 64 bits

int même taille que uint

Nous pouvons donc aussi utiliser cette constante pour déterminer la valeur maximale de int, en prenant cette même réponse et en divisant par 2 puis soustraction 1. c'est à dire: (1 << bits.UintSize) / 2 - 1

Et la valeur minimale de int, en décalant 1 par autant de bits et en divisant le résultat par -2. c'est à dire: (1 << bits.UintSize) / -2

En résumé:

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

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

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

exemple complet (devrait être le même que ci-dessous)

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)
}
3
Will Palmer