Il s'agit d'une question d'exploration, ce qui signifie que je ne sais pas exactement de quoi il s'agit, mais je pense qu'il s'agit du plus grand entier de Bash. Quoi qu'il en soit, je vais le définir ostensivement.
$ echo $((1<<8))
256
Je produis un entier en décalant un peu. Jusqu'où puis-je aller?
$ echo $((1<<80000))
1
Pas si loin, apparemment. (1 est inattendu, et je vais y revenir.) Mais,
$ echo $((1<<1022))
4611686018427387904
est toujours positif. Mais non:
$ echo $((1<<1023))
-9223372036854775808
Et un pas plus loin,
$ echo $((1<<1024))
1
Pourquoi 1? Et pourquoi ce qui suit?
$ echo $((1<<1025))
2
$ echo $((1<<1026))
4
Quelqu'un aimerait-il analyser cette série?
MISE À JOUR
Ma machine:
$ 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- arrête d'être méchant'
la source
la source
Réponses:
Bash utilise des
intmax_t
variables pour l'arithmétique . Sur votre système, elles ont une longueur de 64 bits, donc:lequel est
en binaire (1 suivi de 62 0s). Déplacer cela à nouveau:
lequel est
en binaire (63 0s), en arithmétique du complément à deux.
Pour obtenir le plus grand entier représentable, vous devez soustraire 1:
lequel est
en binaire.
Comme indiqué dans la réponse d' ilkkachu , le décalage prend le décalage modulo 64 sur les processeurs x86 64 bits (que ce soit avec ou ), ce qui explique le comportement que vous voyez:
RCL
SHL
est équivalent à
$((1<<0))
. Ainsi$((1<<1025))
est$((1<<1))
,$((1<<1026))
est$((1<<2))
...Vous trouverez les définitions de type et les valeurs maximales dans
stdint.h
; sur votre système:la source
-
a une priorité plus élevée que<<
.echo $((1<<63-1))
me donne4611686018427387904
.$((1<<63-1))
est égal$(((1<<63)-1))
.Du
CHANGES
fichier pourbash
2.05b:Sur les machines x86_64
intmax_t
correspond aux entiers 64 bits signés. Vous obtenez donc des valeurs significatives entre-2^63
et2^63-1
. En dehors de cette plage, vous obtenez simplement des enveloppements.la source
-2^63
et2^63-1
, inclus.Un décalage de 1024 donne un, car la quantité de décalage est effectivement prise modulo le nombre de bits (64), donc
1024 === 64 === 0
, et1025 === 65 === 1
.Décaler quelque chose d'autre qu'un a
1
indique clairement qu'il ne s'agit pas d'une rotation de bits, car les bits supérieurs ne s'enroulent pas vers le bas avant que la valeur de décalage ne soit (au moins) 64:Il se peut que ce comportement dépende du système. Le code bash lié à Stephen montre juste un décalage simple, sans vérification de la valeur de droite. Si je me souviens bien, les processeurs x86 n'utilisent que les six derniers bits de la valeur de décalage (en mode 64 bits), de sorte que le comportement peut provenir directement du langage machine. De plus, je pense que les décalages de plus que la largeur de bit ne sont pas clairement définis non plus en C (
gcc
avertit pour cela).la source
Jusqu'à ce que la représentation entière s'enroule (la valeur par défaut dans la plupart des shells).
Un entier 64 bits enveloppe généralement at
2**63 - 1
.C'est
0x7fffffffffffffff
ou9223372036854775807
en décembre.Ce nombre «+1» devient négatif.
C'est la même chose que
1<<63
:Après cela, le processus se répète.
Le résultat dépend
mod 64
de la valeur de décalage [a] .[a] Extrait de: Intel® 64 et IA-32 Architectures Software Developer's Manual: Volume 2 Le nombre est masqué à 5 bits (ou 6 bits si en mode 64 bits et REX.W est utilisé). La plage de comptage est limitée à 0 à 31 (ou 63 si le mode 64 bits et REX.W est utilisé). .
Aussi: rappelez-vous que
$((1<<0))
c'est1
Donc, tout dépend de la façon dont le nombre est proche d'un multiple de 64.
Tester la limite:
La manière robuste de tester quel est l'entier positif (et négatif) maximum est de tester chaque bit à tour de rôle. Ses moins de 64 étapes pour la plupart des ordinateurs de toute façon, ce ne sera pas trop lent.
frapper
Tout d'abord, nous avons besoin du plus grand entier du formulaire
2^n
(ensemble de 1 bit suivi de zéros). Nous pouvons le faire en décalant vers la gauche jusqu'à ce que le décalage suivant rend le nombre négatif, également appelé «bouclage»:Où
b
est le résultat: la valeur avant le dernier quart de travail qui échoue à la boucle.Ensuite, nous devons essayer chaque bit pour savoir lesquels affectent le signe de
e
:Le nombre entier maximum (
intmax
) résulte de la dernière valeur ded
.Du côté négatif (moins que
0
), nous répétons tous les tests mais testons quand un bit peut être mis à 0 sans s'enrouler.Voici un test complet avec impression de toutes les étapes (pour bash):
sh
Traduit dans presque n'importe quel shell:
En exécutant ce qui précède pour de nombreux shells,
tous (sauf bash 2.04 et mksh) ont accepté des valeurs allant jusqu'à (
2**63 -1
) sur cet ordinateur.Il est intéressant de signaler que la coquille att :
imprimé une erreur sur les valeurs de
$((2^63))
, pas ksh cependant.la source