Il valore massimo per un tipo int in Vai


132

Come si specifica il valore massimo rappresentabile per un unsignedtipo intero?

Vorrei sapere come inizializzare minnel loop sottostante che calcola iterativamente lunghezze min e max da alcune strutture.

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
}

in modo che la prima volta attraverso il confronto, minLen >= n.


2
dai un'occhiata a questo frammento int(^uint(0) >> 1) // largest intestratto da golang.org/doc/effective_go.html#printing
Victor

Risposte:


218

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

La parte tedesca:

Poiché i tipi interi usano l'aritmetica del complemento di due, puoi dedurre i valori della costante min / max per inte uint. Per esempio,

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

Secondo il commento di @ 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
Usa quelli disponibili in math: golang.org/pkg/math/#pkg-constants , vorrai math.MaxInt32molto probabilmente.
Charles L.

7
Qualcuno può spiegare esattamente cosa fanno ^ uint (0) e ^ uint (0) >> 1?
Arijoon,

16
@Arijoon, ^ significa invertire i bit nell'espressione quindi se: uint (0) == 0000 ... 0000 (esattamente 32 o 64 zero bit in base all'architettura di destinazione della build) quindi ^ unità (0) == 1111 ... 1111 che ci dà il valore massimo per l'intero senza segno (tutti). Ora, quando si parla di numeri interi con segno, il primo bit (il più significativo) viene utilizzato per memorizzare il segno quindi al valore massimo int con segno - dobbiamo spostare tutti i bit a destra che ci danno ^ uint (0) >> 1 = = 0111 ... 1111. Che dà il numero intero positivo massimo.
ninjaboy

4
@CharlesL. che dire solo del tipo int?
user960567

1
So che è passato del tempo, ma nel caso in cui qualcuno venga qui oggi e veda il commento-domanda di @ user960567: il inttipo è lungo 32 bit su un sistema a 32 bit e lungo 64 bit su un sistema a 64 bit. Vedi qui .
Christoph Harms-Ensink,

73

https://golang.org/ref/spec#Numeric_types per limiti di tipo fisico.

I valori massimi sono definiti nel pacchetto matematico, quindi nel tuo caso: math.MaxUint32

Fai attenzione perché non c'è troppopieno: l'incremento del massimo passato provoca un avvolgimento.


2
Grazie. In realtà sto usando uint, no uint32. Il lene non capusare così voglio usare qualcosa che corrisponda alla dimensione di quelli su tutte le architetture. definisce un gruppo di ma nessuno per uno o `int. intint32math/const.goMax<type>uint
Mike Samuel,

Lo cambierei in uint32 o unit64 per assicurarmi che sia portatile su tutte le architetture. Lo faccio con tutto religiosamente. Ho attraversato anni di inferno porting C tra architetture e posso dire che "essere esplicito" aiuterà notevolmente in seguito.
Eliminato il

Grazie. Il mio codice lo controlla uint(len(...)) < thing.minLenma non so se uint64(int)è e rimarrà un comportamento definito.
Mike Samuel,

1
Se non lo sai, leggi le specifiche sopra collegate ... in particolare golang.org/doc/go_spec.html#Conversions . Esiste un'attenta definizione di "conversioni tra tipi numerici".
Anschel Schaffer-Cohen,

29

Vorrei usare il mathpacchetto per ottenere il valore massimo e il valore minimo:

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
}

Uscita:

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
Questo codice non funziona. L' int64intorno di overflow dei due , che è ciò che accade se non si digitano esplicitamente le costanti prima dell'interpolazione di stringhe. Utilizzare int64(math.MaxInt64)invece, vedere stackoverflow.com/questions/16474594/...
domoarigato

3
Ma per il resto, è una risposta migliore di quella accettata. :)
domoarigato,

cosa succede se si utilizza int64 su un computer con dimensioni delle parole a 32 bit? in C, il compilatore decide INT_MIN
segue_segway

12

Inizialmente ho usato il codice preso dal thread di discussione che @nmichaels ha usato nella sua risposta. Ora uso un calcolo leggermente diverso. Ho incluso alcuni commenti nel caso in cui qualcun altro abbia la stessa query di @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
)

Gli ultimi due passaggi funzionano a causa del modo in cui i numeri positivi e negativi sono rappresentati nell'aritmetica del complemento a due. La sezione Specifiche lingua Go sui tipi numerici rimanda il lettore all'articolo Wikipedia pertinente . Non l'ho letto, ma ho appreso del complemento a due dal libro Code di Charles Petzold , che è un'introduzione molto accessibile ai fondamenti dei computer e della codifica.

Ho inserito il codice sopra (meno la maggior parte dei commenti) in un pacchetto matematico intero .


9

Riepilogo rapido:

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

Sfondo:

Come presumo tu sappia, il uinttipo ha le stesse dimensioni di uno uint32o uint64, a seconda della piattaforma su cui ti trovi. Di solito, si userebbe la versione non dimensionata di questi solo quando non vi è alcun rischio di avvicinarsi al valore massimo, poiché la versione senza una specifica di dimensione può utilizzare il tipo "nativo", a seconda della piattaforma, che tende ad essere più veloce.

Si noti che tende ad essere "più veloce" perché l'utilizzo di un tipo non nativo richiede talvolta l'esecuzione di ulteriori controlli matematici e di limiti da parte del processore, al fine di emulare il numero intero più grande o più piccolo. Tenendo presente ciò, tieni presente che le prestazioni del processore (o del codice ottimizzato del compilatore) saranno quasi sempre migliori rispetto all'aggiunta del tuo codice di controllo dei limiti, quindi se c'è qualche rischio che entri in gioco, potrebbe rendere ha senso usare semplicemente la versione di dimensioni fisse e lasciare che l'emulazione ottimizzata gestisca eventuali ricadute.

Detto questo, ci sono ancora alcune situazioni in cui è utile sapere con cosa stai lavorando.

Il pacchetto " matematica / bit " contiene la dimensione di uint, in bit. Per determinare il valore massimo, spostare 1di quel numero di bit, meno 1. cioè:(1 << bits.UintSize) - 1

Si noti che quando si calcola il valore massimo di uint, in genere è necessario inserirlo esplicitamente in una uint(o più grande) variabile, altrimenti il ​​compilatore potrebbe non riuscire, poiché per impostazione predefinita si tenterà di assegnare quel calcolo in un segno int(dove, come dovrebbe essere ovvio, non si adatterebbe), quindi:

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

Questa è la risposta diretta alla tua domanda, ma ci sono anche un paio di calcoli correlati che potrebbero interessarti.

Secondo le specifiche , uinte inthanno sempre le stesse dimensioni.

uint 32 o 64 bit

int stesse dimensioni di uint

Quindi possiamo anche usare questa costante per determinare il valore massimo di int, prendendo quella stessa risposta e dividendola 2poi sottraendo 1. vale a dire:(1 << bits.UintSize) / 2 - 1

E il valore minimo di int, spostando 1per molti bit e dividendo il risultato per -2. vale a dire:(1 << bits.UintSize) / -2

In sintesi:

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

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

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

esempio completo (dovrebbe essere lo stesso di seguito)

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

Grazie. I tuoi avvertimenti sui numeri nativi sono ben dichiarati e non ero a conoscenza di matematica / bit.
Mike Samuel,

sia a 32 che a 64 bit, con le stesse dimensioni di uint. Come possono avere le stesse dimensioni se uno ha un segno e l'altro no?
themiDdest

Hanno la stessa dimensione in bit, non hanno gli stessi valori massimo / minimo. Uno dei bit di quella dimensione è il bit del segno. (la /2parte è ciò che rimuove quel bit dalla considerazione quando si calcola la dimensione di min / max per int64)
Will Palmer


4

Un modo per risolvere questo problema è ottenere i punti di partenza dai valori stessi:

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

Un pacchetto leggero li contiene (così come altri limiti di tipi int e alcune funzioni integer ampiamente utilizzate):

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.