Esta es una pregunta de exploración, lo que significa que no estoy completamente seguro de qué se trata esta pregunta, pero creo que se trata del mayor número entero en Bash. De todos modos, lo definiré con ostentación.
$ echo $((1<<8))
256
Estoy produciendo un número entero cambiando un poco. ¿Hasta dónde puedo llegar?
$ echo $((1<<80000))
1
No tan lejos, al parecer. (1 es inesperado, y volveré sobre ello.) Pero,
$ echo $((1<<1022))
4611686018427387904
Sigue siendo positivo. No esto, sin embargo:
$ echo $((1<<1023))
-9223372036854775808
Y un paso más allá,
$ echo $((1<<1024))
1
¿Por qué 1? ¿Y por qué lo siguiente?
$ echo $((1<<1025))
2
$ echo $((1<<1026))
4
¿A alguien le gustaría analizar esta serie?
ACTUALIZAR
Mi maquina:
$ uname -a
Linux tomas-Latitude-E4200 4.4.0-47-generic #68-Ubuntu SMP Wed Oct 26 19:39:52 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
bash
arithmetic
Gilles 'SO- deja de ser malvado'
fuente
fuente
Respuestas:
Bash usa
intmax_t
variables para la aritmética . En su sistema, estos tienen 64 bits de longitud, así que:cual es
en binario (1 seguido de 62 0s). Cambia eso de nuevo:
cual es
en binario (63 0s), en aritmética del complemento a dos.
Para obtener el mayor entero representable, debe restar 1:
cual es
en binario
Como se señaló en la respuesta de ilkkachu , el cambio toma el módulo de compensación 64 en CPU x86 de 64 bits (ya sea que use o ), lo que explica el comportamiento que está viendo:
RCL
SHL
es equivalente a
$((1<<0))
. Así$((1<<1025))
es$((1<<1))
,$((1<<1026))
es$((1<<2))
...Encontrará las definiciones de tipo y los valores máximos en
stdint.h
; en su sistema:fuente
-
tiene mayor prioridad que<<
.echo $((1<<63-1))
me da4611686018427387904
.$((1<<63-1))
es igual$(((1<<63)-1))
.Del
CHANGES
archivo parabash
2.05b:En máquinas x86_64
intmax_t
corresponde a enteros de 64 bits con signo. Entonces obtienes valores significativos entre-2^63
y2^63-1
. Fuera de ese rango, solo obtienes envolturas.fuente
-2^63
y2^63-1
, inclusive.El desplazamiento por 1024 da un uno, porque la cantidad de desplazamiento se toma efectivamente módulo el número de bits (64), entonces
1024 === 64 === 0
, y1025 === 65 === 1
.Al cambiar algo distinto de a,
1
queda claro que no es una rotación de bits, ya que los bits más altos no se ajustan al extremo inferior antes de que el valor de desplazamiento sea (al menos) 64:Puede ser que este comportamiento dependa del sistema. El código de bash con el que se vinculó Stephen muestra solo un cambio simple, sin verificar el valor de la mano derecha. Si no recuerdo mal, los procesadores x86 solo usan los seis bits inferiores del valor de desplazamiento (en modo de 64 bits), por lo que el comportamiento puede ser directamente del lenguaje de la máquina. Además, creo que los cambios en más del ancho de bits tampoco están claramente definidos en C (
gcc
advierte eso).fuente
Hasta que la representación entera se envuelva (el valor predeterminado en la mayoría de los shells).
Un entero de 64 bits generalmente se envuelve en
2**63 - 1
.Eso es
0x7fffffffffffffff
o9223372036854775807
en diciembre.Ese número '+1' se vuelve negativo.
Eso es lo mismo que
1<<63
, por lo tanto:Después de eso, el proceso se repite nuevamente.
El resultado depende
mod 64
del valor de desplazamiento [a] .[a] De: Intel® 64 e IA-32 Architectures Software Developer's Manual: Volumen 2 El recuento se enmascara a 5 bits (o 6 bits si está en modo de 64 bits y se utiliza REX.W). El rango de conteo está limitado de 0 a 31 (o 63 si se usa el modo de 64 bits y REX.W). .
Además: recuerda que
$((1<<0))
es1
Entonces, todo depende de qué tan cerca esté el número a un múltiplo de 64.
Probar el límite:
La forma sólida de probar cuál es el número entero positivo (y negativo) máximo es probar cada bit por turno. De todos modos, tiene menos de 64 pasos para la mayoría de las computadoras, no será demasiado lento.
golpetazo
Primero necesitamos el mayor número entero de la forma
2^n
(conjunto de 1 bit seguido de ceros). Podemos hacerlo desplazándonos hacia la izquierda hasta que el próximo desplazamiento haga que el número sea negativo, también llamado "ajuste"Dónde
b
está el resultado: el valor antes del último turno que falla el ciclo.Luego, debemos intentar cada poco para descubrir cuáles afectan el signo de
e
:El número entero máximo (
intmax
) resulta del último valor ded
.En el lado negativo (menos de
0
), repetimos todas las pruebas, pero comprobamos cuándo se puede hacer un bit 0 sin ajustar.Una prueba completa con la impresión de todos los pasos es la siguiente (para bash):
sh
Traducido a casi cualquier shell:
Al ejecutar lo anterior para muchos shells,
todos (excepto bash 2.04 y mksh) aceptaron valores hasta (
2**63 -1
) en esta computadora.Es interesante informar que el shell att :
imprimió un error en los valores de
$((2^63))
, no ksh sin embargo.fuente