Esta é uma questão de exploração, o que significa que não tenho certeza do que se trata, mas acho que é o maior número inteiro no Bash. De qualquer forma, vou defini-lo ostensivamente.
$ echo $((1<<8))
256
Estou produzindo um número inteiro deslocando um pouco. Até onde posso ir?
$ echo $((1<<80000))
1
Não tão longe, aparentemente. (1 é inesperado e voltarei a ele.) Mas,
$ echo $((1<<1022))
4611686018427387904
ainda é positivo. Não é isso, no entanto:
$ echo $((1<<1023))
-9223372036854775808
E um passo adiante,
$ echo $((1<<1024))
1
Por que 1? E por que o seguinte?
$ echo $((1<<1025))
2
$ echo $((1<<1026))
4
Alguém gostaria de analisar esta série?
ATUALIZAR
Minha máquina:
$ 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- parar de ser mau'
fonte
fonte
Respostas:
O Bash usa
intmax_t
variáveis para aritmética . No seu sistema, eles têm 64 bits de comprimento, portanto:qual é
em binário (1 seguido por 62 0s). Mude isso novamente:
qual é
em binário (63 0s), na aritmética do complemento de dois.
Para obter o maior número inteiro representável, você precisa subtrair 1:
qual é
em binário.
Como fora apontado em ilkkachu 's resposta , mudando leva o deslocamento módulo 64 em 64-bit x86 CPUs (seja usando
RCL
ouSHL
), o que explica o comportamento que você está vendo:é equivalente a
$((1<<0))
. Assim$((1<<1025))
é$((1<<1))
,$((1<<1026))
é$((1<<2))
...Você encontrará as definições de tipo e os valores máximos em
stdint.h
; no seu sistema:fonte
-
tem maior precedência do que<<
.echo $((1<<63-1))
me dá4611686018427387904
.$((1<<63-1))
é igual a$(((1<<63)-1))
.Do
CHANGES
arquivo parabash
2.05b:Em máquinas x86_64
intmax_t
corresponde a números inteiros de 64 bits assinados. Então você obtém valores significativos entre-2^63
e2^63-1
. Fora desse intervalo, você apenas recebe envolvimentos.fonte
-2^63
e2^63-1
, inclusive.Mudar para 1024 fornece um, porque a quantidade de deslocamento é efetivamente tomada modulando o número de bits (64), então
1024 === 64 === 0
, e1025 === 65 === 1
.Mudar algo diferente de a
1
deixa claro que não é uma rotação de bits, já que os bits mais altos não se aproximam da extremidade inferior antes que o valor da mudança seja (pelo menos) 64:Pode ser que esse comportamento dependa do sistema. O código do bash ao qual Stephen se vinculou mostra apenas uma mudança simples, sem qualquer verificação do valor à direita. Se bem me lembro, os processadores x86 usam apenas os seis bits inferiores do valor de deslocamento (no modo de 64 bits); portanto, o comportamento pode ser diretamente da linguagem da máquina. Além disso, acho que as mudanças além da largura do bit também não estão claramente definidas em C (
gcc
alerta para isso).fonte
Até que a representação inteira envolva (o padrão na maioria dos shells).
Um número inteiro de 64 bits geralmente envolve em
2**63 - 1
.Isso é
0x7fffffffffffffff
ou9223372036854775807
em dezembro.Esse número '+1' se torna negativo.
É o mesmo que
1<<63
, assim:Depois disso, o processo se repete novamente.
O resultado depende
mod 64
do valor de mudança [a] .[a] De: Manual do desenvolvedor de software das arquiteturas Intel® 64 e IA-32: Volume 2 A contagem é mascarada em 5 bits (ou 6 bits se estiver no modo de 64 bits e REX.W estiver sendo usado). O intervalo de contagem é limitado de 0 a 31 (ou 63 se o modo de 64 bits e o REX.W forem usados). .
Lembre-se também de que
$((1<<0))
é1
Portanto, tudo depende da proximidade do número de um múltiplo de 64.
Testando o limite:
A maneira robusta de testar qual é o número máximo positivo (e negativo) máximo é testar cada um por vez. Seus menos de 64 passos para a maioria dos computadores, de qualquer maneira, não será muito lento.
bater
Primeiro, precisamos do maior número inteiro do formulário
2^n
(conjunto de 1 bit seguido por zeros). Podemos fazer isso deslocando a esquerda até o próximo turno tornar o número negativo, também chamado de "contornar":Onde
b
está o resultado: o valor antes do último turno que falha no loop.Então, precisamos tentar todos os detalhes para descobrir quais afetam o sinal de
e
:O número inteiro máximo (
intmax
) resulta do último valor ded
.No lado negativo (menos que
0
), repetimos todos os testes, mas testamos quando um pouco pode ser feito 0 sem envolver.Um teste completo com a impressão de todas as etapas é este (para o bash):
sh
Traduzido para quase qualquer shell:
Executando o descrito acima para muitos shells,
todos (exceto o bash 2.04 e o mksh) aceitaram valores de até (
2**63 -1
) neste computador.É interessante relatar que o shell att :
imprimiu um erro nos valores de
$((2^63))
, mas não no ksh.fonte