¿Cómo se especifica el valor máximo representable para un unsigned
tipo entero?
Me gustaría saber cómo inicializar min
en el ciclo a continuación que calcula iterativamente las longitudes mínimas y máximas de algunas estructuras.
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
}
por lo que la primera vez a través de la comparación, minLen >= n
.
int(^uint(0) >> 1) // largest int
extraído de golang.org/doc/effective_go.html#printingRespuestas:
https://groups.google.com/group/golang-nuts/msg/71c307e4d73024ce?pli=1
La parte pertinente:
Según el comentario de @ CarelZA:
fuente
math
: golang.org/pkg/math/#pkg-constants , lomath.MaxInt32
más probable es que desee .int
tipo tiene 32 bits de largo en un sistema de 32 bits y 64 bits de largo en un sistema de 64 bits. Ver aquí .https://golang.org/ref/spec#Numeric_types para límites de tipo físico.
Los valores máximos se definen en el paquete matemático, por lo que en su caso: math.MaxUint32
Tenga cuidado, ya que no hay desbordamiento: el incremento del pasado máximo provoca una envoltura.
fuente
uint
, nouint32
. Ellen
y nocap
uso, por lo que quiero usar algo que coincida con el tamaño de aquellos en todas las arquitecturas. define un montón de pero ninguno para cualquiera o `int.int
int32
math/const.go
Max<type>
uint
uint(len(...)) < thing.minLen
pero no sé siuint64(int)
es y seguirá siendo un comportamiento definido.Usaría el
math
paquete para obtener el valor máximo y el valor mínimo:Ouput:
fuente
int64
overflow de los dos int, que es lo que sucede si no escribe explícitamente constantes antes de la interpolación de cadenas. Utilice en suint64(math.MaxInt64)
lugar, consulte stackoverflow.com/questions/16474594/…Originalmente usé el código tomado del hilo de discusión que @nmichaels usó en su respuesta. Ahora uso un cálculo ligeramente diferente. He incluido algunos comentarios en caso de que alguien más tenga la misma consulta que @Arijoon
Los dos últimos pasos funcionan debido a cómo se representan los números positivos y negativos en la aritmética del complemento a dos. La sección de especificación del lenguaje Go sobre Tipos numéricos remite al lector al artículo relevante de Wikipedia . No he leído eso, pero aprendí sobre el complemento de dos del libro Code de Charles Petzold , que es una introducción muy accesible a los fundamentos de las computadoras y la codificación.
Puse el código de arriba (menos la mayoría de los comentarios) en un pequeño paquete matemático entero .
fuente
Sumario rápido:
Antecedentes:
Como supongo que ya sabes, el
uint
tipo es del mismo tamaño que seauint32
ouint64
, dependiendo de la plataforma que se encuentra. Por lo general, uno usaría la versión sin tamaño de estos solo cuando no haya riesgo de acercarse al valor máximo, ya que la versión sin una especificación de tamaño puede usar el tipo "nativo", dependiendo de la plataforma, que tiende a ser más rápido.Tenga en cuenta que tiende a ser "más rápido" porque el uso de un tipo no nativo a veces requiere que el procesador realice una comprobación matemática y de límites adicional para emular el número entero más grande o más pequeño. Con eso en mente, tenga en cuenta que el rendimiento del procesador (o el código optimizado del compilador) casi siempre será mejor que agregar su propio código de verificación de límites, por lo que si existe algún riesgo de que entre en juego, puede tiene sentido usar simplemente la versión de tamaño fijo y dejar que la emulación optimizada se encargue de las consecuencias de eso.
Dicho esto, todavía hay algunas situaciones en las que es útil saber con qué está trabajando.
El paquete " matemáticas / bits " contiene el tamaño de
uint
, en bits. Para determinar el valor máximo, cambie1
esa cantidad de bits, menos 1. es decir:(1 << bits.UintSize) - 1
Tenga en cuenta que al calcular el valor máximo de
uint
, generalmente tendrá que ponerlo explícitamente en unauint
variable (o más grande), de lo contrario, el compilador puede fallar, ya que de forma predeterminada intentará asignar ese cálculo a un signoint
(donde, como debería sea obvio, no encajaría), entonces:Esa es la respuesta directa a su pregunta, pero también hay algunos cálculos relacionados que pueden interesarle.
Según la especificación ,
uint
yint
siempre son del mismo tamaño.Entonces, también podemos usar esta constante para determinar el valor máximo de
int
, tomando esa misma respuesta y dividiendo para2
luego restar1
. es decir:(1 << bits.UintSize) / 2 - 1
Y el valor mínimo de
int
, cambiando1
por tantos bits y dividiendo el resultado entre-2
. es decir:(1 << bits.UintSize) / -2
En resumen:
MaxUint:
(1 << bits.UintSize) - 1
MaxInt:
(1 << bits.UintSize) / 2 - 1
MinInt:
(1 << bits.UintSize) / -2
ejemplo completo (debe ser el mismo que se muestra a continuación)
fuente
/2
parte es lo que elimina ese bit de consideración al calcular el tamaño de min / max para int64)Desde lib matemática: https://github.com/golang/go/blob/master/src/math/const.go#L39
fuente
Una forma de resolver este problema es obtener los puntos de partida de los valores mismos:
fuente
Un paquete liviano los contiene (así como otros límites de tipos int y algunas funciones enteras ampliamente utilizadas):
fuente
fuente