218 votes

La valeur maximale d'un type int en Go

Comment peut-on spécifier la valeur maximale représentable pour une unsigned Type d'entier ?

Je voudrais savoir comment initialiser min dans la boucle ci-dessous qui calcule itérativement les longueurs min et max à partir de quelques 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
}

pour que la première fois, la comparaison soit faite, minLen >= n .

5 votes

Jetez un coup d'œil à cet extrait int(^uint(0) >> 1) // largest int extrait de golang.org/doc/effective_go.html#impression

313voto

nmichaels Points 21955

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

La partie germaine :

Puisque les types entiers utilisent l'arithmétique de complément à deux, vous pouvez déduire les valeurs constantes min/max pour int y uint . Par exemple,

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

Conformément au 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

162 votes

Utilisez ceux qui sont disponibles dans math : golang.org/pkg/math/#pkg-constants vous voudriez math.MaxInt32 le plus probable.

10 votes

Quelqu'un peut-il expliquer exactement ce que font ^uint(0) et ^uint(0) >> 1 ?

27 votes

@Arijoon, ^ signifie inverser les bits dans l'expression, donc si : uint(0) == 0000...0000 (exactement 32 ou 64 bits de zéro selon l'architecture cible de construction) alors ^unit(0) == 1111...1111 qui nous donne la valeur maximale pour l'entier non signé (tous les uns). Maintenant, lorsque vous parlez d'un entier signé, le premier bit (le plus significatif) est utilisé pour stocker le signe, donc pour la valeur maximale de l'entier signé, nous devons décaler tous les bits vers la droite, ce qui nous donne ^uint(0) >> 1 == 0111...1111. Ce qui donne le nombre entier positif maximum.

90voto

Deleted Points 2693

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

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

Attention, il n'y a pas de débordement - l'incrémentation au-delà de la valeur maximale provoque un retournement.

4 votes

Merci. En fait, j'utilise uint pas uint32 . Le site len y cap utiliser int no int32 Je veux donc utiliser quelque chose qui correspond à la taille de ces derniers sur toutes les architectures. math/const.go définit un ensemble de Max<type> mais aucun pour l'un ou l'autre uint ou `int.

0 votes

Je le changerais en uint32 ou unit64 pour être sûr qu'il soit portable sur toutes les architectures. Je fais cela avec tout religieusement. J'ai vécu des années d'enfer à porter du C entre architectures et je peux dire qu'être explicite m'aidera considérablement par la suite.

1 votes

Merci. Mon code comporte des contrôles qui uint(len(...)) < thing.minLen mais je ne sais pas si uint64(int) est et restera un comportement défini.

74voto

Gujarat Santana Points 379

J'utiliserais math pour obtenir les valeurs maximales et minimales des entiers :

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
}

Sortie :

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

3 votes

Ce code ne fonctionne pas. Les deux int64 C'est ce qui se passe si vous ne tapez pas explicitement les constantes avant l'interpolation des chaînes. Utilisez int64(math.MaxInt64) à la place, voir stackoverflow.com/questions/16474594/

3 votes

Mais sinon, c'est une meilleure réponse que celle acceptée :)

0 votes

Que se passe-t-il si vous utilisez int64 sur une machine avec une taille de mot de 32 bits ? En C, le compilateur décide de la valeur INT_MIN.

22voto

Will Palmer Points 2614

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
)

Le contexte :

Comme je suppose que vous le savez, le uint est de la même taille que l'un ou l'autre uint32 o uint64 en fonction de la plateforme sur laquelle vous vous trouvez. En général, on n'utilise la version sans taille que lorsqu'il n'y a aucun risque de s'approcher de la valeur maximale, car la version sans spécification de taille peut utiliser le type "natif", selon la plate-forme, qui a tendance à être plus rapide.

Notez qu'elle a tendance à être "plus rapide" parce que l'utilisation d'un type non natif nécessite parfois des calculs supplémentaires et un contrôle des limites à effectuer par le processeur, afin d'émuler l'entier plus grand ou plus petit. En gardant cela à l'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 contrôle des limites, donc s'il y a un risque que cela entre en jeu, il peut être judicieux d'utiliser simplement la version à taille fixe et de laisser l'émulation optimisée gérer toutes les retombées.

Cela dit, il y a toujours des situations où il est utile de savoir avec quoi l'on travaille.

Le paquet " maths/bits "contient la taille de uint en bits. Pour déterminer la valeur maximale, on décale 1 par ce nombre de bits, moins 1. c'est-à-dire : (1 << bits.UintSize) - 1

Notez que lors du calcul de la valeur maximale de uint vous devrez généralement l'insérer explicitement dans un fichier de type uint (ou plus), sinon le compilateur risque d'échouer, car il tentera par défaut d'affecter ce calcul à une variable signée de type int (où, comme cela devrait être évident, il ne conviendrait pas), donc :

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

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

Selon le spec , uint y int sont toujours de la même taille.

uint soit 32 ou 64 bits

int la même taille que uint

Nous pouvons donc également utiliser cette constante pour déterminer la valeur maximale de int en prenant cette même réponse et en divisant par 2 puis en soustrayant 1 . ie : (1 << bits.UintSize) / 2 - 1

Et la valeur minimale de int en déplaçant 1 par autant de bits et en divisant le résultat par -2 . ie : (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)
}

14voto

crantok Points 184

J'ai utilisé à l'origine le code tiré du fil de discussion que @nmichaels a utilisé dans sa réponse. J'utilise maintenant un calcul légèrement différent. J'ai inclus quelques commentaires au cas où quelqu'un d'autre aurait la même question 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 grâce à la façon dont les nombres positifs et négatifs sont représentés dans l'arithmétique du complément à deux. La section des spécifications du langage Go sur Types numériques renvoie le lecteur à l'article pertinent Article de Wikipedia . Je ne l'ai pas lu, mais j'ai appris le complément à deux grâce à ce livre. Code de Charles Petzold qui est une introduction très accessible aux principes fondamentaux de l'informatique et du codage.

J'ai mis le code ci-dessus (sans la plupart des commentaires) dans un petit fichier paquet mathématique sur les nombres entiers .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X