Jak określić maksymalną wartość, jaką można przedstawić dla typu unsigned
całkowitego?
Chciałbym wiedzieć, jak zainicjować min
w pętli poniżej, która iteracyjnie oblicza długości minimalne i maksymalne z niektórych struktur.
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
}
tak że po raz pierwszy przez porównania minLen >= n
.
int(^uint(0) >> 1) // largest int
wyodrębniony z golang.org/doc/effective_go.html#printingOdpowiedzi:
https://groups.google.com/group/golang-nuts/msg/71c307e4d73024ce?pli=1
Część niemiecka:
Zgodnie z komentarzem @ 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
źródło
math
: golang.org/pkg/math/#pkg-constants , prawdopodobnie chceszmath.MaxInt32
.int
typ ma długość 32 bity w systemie 32-bitowym i 64 bity w systemie 64-bitowym. Zobacz tutaj .https://golang.org/ref/spec#Numeric_types dla fizycznych ograniczeń typu.
Maksymalne wartości są zdefiniowane w pakiecie matematycznym, więc w twoim przypadku: math.MaxUint32
Uważaj, ponieważ nie ma przepełnienia - przekroczenie wartości maksymalnej powoduje zawijanie.
źródło
uint
, nieuint32
.len
Icap
stosowanieint
nieint32
tak chcę użyć czegoś, co odpowiada wielkości tych wszystkich architekturach.math/const.go
definiuje kilkaMax<type>
, ale żaden z obuuint
lub `int.uint(len(...)) < thing.minLen
ale nie wiem, czyuint64(int)
jest i pozostanie zdefiniowanym zachowaniem.Użyłbym
math
pakietu do uzyskania wartości maksymalnej i minimalnej: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
źródło
int64
Przepełnienie dwóch wartości int, co się dzieje, jeśli nie podasz jawnie stałych przed interpolacją ciągów. Użyjint64(math.MaxInt64)
zamiast tego, zobacz stackoverflow.com/questions/16474594/ ...Pierwotnie użyłem kodu zaczerpniętego z wątku dyskusji, którego @nmichaels użył w swojej odpowiedzi. Teraz używam nieco innego obliczenia. Dołączyłem kilka komentarzy na wypadek, gdyby ktoś inny miał takie samo zapytanie jak @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 )
Ostatnie dwa kroki działają z powodu tego, jak liczby dodatnie i ujemne są reprezentowane w arytmetyce uzupełnień do dwóch. Sekcja specyfikacji języka Go dotycząca typów liczbowych odsyła czytelnika do odpowiedniego artykułu w Wikipedii . Nie czytałem tego, ale dowiedziałem się o uzupełnieniu do dwóch z książki Code Charlesa Petzolda , która jest bardzo przystępnym wprowadzeniem do podstaw komputerów i kodowania.
Umieściłem powyższy kod (bez większości komentarzy) w małym pakiecie matematycznym całkowitoliczbowym .
źródło
Szybkie podsumowanie:
import "math/bits" const ( MaxUint uint = (1 << bits.UintSize) - 1 MaxInt int = (1 << bits.UintSize) / 2 - 1 MinInt int = (1 << bits.UintSize) / -2 )
Tło:
Jak przypuszczam, wiesz,
uint
typ jest tego samego rozmiaru co jeden z nichuint32
lubuint64
, w zależności od platformy, na której się znajdujesz. Zwykle używa się ich wersji bez rozmiaru tylko wtedy, gdy nie ma ryzyka zbliżenia się do wartości maksymalnej, ponieważ wersja bez specyfikacji rozmiaru może używać typu „natywnego”, w zależności od platformy, który jest zwykle szybszy.Zwróć uwagę, że zwykle jest to „szybsze”, ponieważ użycie typu innego niż natywny czasami wymaga dodatkowego obliczenia matematycznego i sprawdzenia granic, które musi wykonać procesor, aby emulować większą lub mniejszą liczbę całkowitą. Mając to na uwadze, pamiętaj, że wydajność procesora (lub zoptymalizowanego kodu kompilatora) prawie zawsze będzie lepsza niż dodawanie własnego kodu sprawdzającego granice, więc jeśli istnieje jakiekolwiek ryzyko, że wejdzie on do gry, może to spowodować sens, aby po prostu użyć wersji o stałym rozmiarze i pozwolić zoptymalizowanej emulacji poradzić sobie z jakimkolwiek opadem.
Mając to na uwadze, nadal istnieją sytuacje, w których warto wiedzieć, z czym się pracuje.
Pakiet „ math / bits ” zawiera rozmiar
uint
w bitach. Aby określić wartość maksymalną, przesuń1
o tyle bitów, minus 1, tj .:(1 << bits.UintSize) - 1
Zwróć uwagę, że podczas obliczania maksymalnej wartości
uint
zazwyczaj musisz umieścić ją jawnie wuint
zmiennej (lub większej), w przeciwnym razie kompilator może się nie powieść, ponieważ domyślnie spróbuje przypisać to obliczenie do podpisanejint
(gdzie, jak powinno byłoby oczywiste, nie pasowałoby), więc:const MaxUint uint = (1 << bits.UintSize) - 1
To jest bezpośrednia odpowiedź na Twoje pytanie, ale istnieje również kilka powiązanych obliczeń, które mogą Cię zainteresować.
Według specyfikacji ,
uint
iint
zawsze są tej samej wielkości.Więc możemy również użyć tej stałej do określenia maksymalnej wartości
int
, biorąc tę samą odpowiedź i dzieląc ją przez2
odjęcie1
. to znaczy:(1 << bits.UintSize) / 2 - 1
I minimalna wartość
int
, przesuwając1
o tyle bitów i dzieląc wynik przez-2
. to znaczy:(1 << bits.UintSize) / -2
W podsumowaniu:
MaxUint:
(1 << bits.UintSize) - 1
MaxInt:
(1 << bits.UintSize) / 2 - 1
MinInt:
(1 << bits.UintSize) / -2
pełny przykład (powinien być taki sam jak poniżej)
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) }
źródło
/2
część usuwa ten bit z rozważenia przy obliczaniu rozmiaru min / max dla int64)Z biblioteki math: https://github.com/golang/go/blob/master/src/math/const.go#L39
package main import ( "fmt" "math" ) func main() { fmt.Printf("max int64: %d\n", math.MaxInt64) }
źródło
Jednym ze sposobów rozwiązania tego problemu jest pobranie punktów początkowych z samych wartości:
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ódło
Zawiera je lekki pakiet (a także ograniczenia innych typów int i niektóre powszechnie używane funkcje liczb całkowitych):
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
źródło
Użyj stałych zdefiniowanych w pakiecie matematycznym :
const ( 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 )
źródło
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
źródło