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
.
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
etuint
. 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
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.
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
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 .
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 }
}
}
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 queuint
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)
}