Quelle est la valeur maximale d'une variable shell bash numérique?

17

Je suis curieux de savoir ce qui se passe lorsqu'une variable numérique dans bash est incrémentée sans l'arrêter délibérément. Quelle taille le nombre peut-il atteindre? Va-t-il déborder et devenir négatif et continuer à augmenter pour toujours? Va-t-il se casser et s'arrêter à un moment donné?

J'utilise un processeur AMD x86_64, mais je serais heureux d'entendre également des réponses 32 bits, spécifiez simplement de quoi vous parlez. J'utilise Fedora21 64bit.

J'ai googlé loin et largement, mais je n'ai pas trouvé cette friandise spécifique pour une raison étrange. Il semble que ce serait une information de base dans tous les manuels et autres.

Maximum d'énergie
la source
3
Que diriez-vous d'imprimer certains pouvoirs de 2 en entrée:for i in {0..70}; do echo 2 to the power of $i = $((2**i)); done
mpy
1
Si vous voulez de grands nombres, vous pouvez passer à celui kshqui bashksh -c 'echo $((2**1023))'8.98846567431157954e+307
utilise l'
Je garderai ksh à l'esprit si j'ai besoin de virgule flottante ou de valeurs dans la stratosphère, la virgule flottante peut être très utile. Mais cette question est simplement pour que je connaisse les limites de mon système, ce n'est pas parce que j'ai besoin de dépasser ses limites. Je ferai quelque chose comme mpy le suggère, je n'ai pas commencé parce que je ne voulais pas risquer de provoquer un plantage du système.
Max Power

Réponses:

22

Cela peut se résumer à votre version de bash, votre système d'exploitation et votre architecture CPU. Pourquoi ne l'essayez-vous pas vous-même? Définissez une variable sur (2 ^ 31) -1, puis incrémentez-la, définissez-la sur 2 ^ 32, puis incrémentez-la, définissez-la sur 2 ^ 64, puis incrémentez-la, etc.

Ici, je viens de l'essayer moi-même sur mon Core i7 Mac exécutant OS X "El Capitan" v10.11.3, et il semble que bash utilise des entiers 64 bits signés.

$ uname -a
Darwin Spiff.local 15.3.0 Darwin Kernel Version 15.3.0: jeu 10 déc 18:40:58 PST 2015; racine: xnu-3248.30.4 ~ 1 / RELEASE_X86_64 x86_64
$ bash --version
bash --version
GNU bash, version 3.2.57 (1) -release (x86_64-apple-darwin15)
Copyright (C) 2007 Free Software Foundation, Inc.
$
$ ((X = 2 ** 16)); écho $ X
65536 <- d'accord, au moins UInt16
$ ((X = 2 ** 32)); écho $ X
4294967296 <- d'accord, au moins UInt32
$ ((X = 2 ** 64)); écho $ X
0 <- oups, pas UInt64
$ ((X = (2 ** 63) -1)); écho $ X
9223372036854775807 <- d'accord, au moins SInt64
$ ((X ++)); écho $ X
-9223372036854775808 <- négatif débordé et enveloppé. Doit être SInt64
Spiff
la source
3

J'ai mis en place une boucle. while return status is 0 increment a variable with addition and print the variable to stdout Je l'ai démarré un peu moins de 2 ^ 31, je l'ai laissé passer sans problème à la fois 2 ^ 31 et 2 ^ 32, je l'ai arrêté, puis j'ai défini la valeur initiale à un peu moins de 2 ^ 63. Le résultat a été qu'il est passé sans interruption de 9.22e18 à -9.22e18 et a continué à augmenter positivement. (vers zéro)

Juste pour vérifier que mon while [ $? -eq 0 ]utilisait réellement l'état de sortie des commandes dans la boucle while, n'utilisant pas l'état de sortie du script précédent ou une bizarrerie, je l'ai également exécuté avec une commande supplémentaire à l'intérieur de la boucle conçue pour créer une sortie non nulle statut à des incréments particuliers.

Il est donc signé, il roulera plutôt que de s'arrêter à la valeur maximale, et il le fait sans aucun message d'erreur. Il est donc possible de se retrouver dans une boucle vraiment infinie. Il ne limite pas le matériel 64 bits et le système d'exploitation Linux 64 bits à un ancien standard 16 ou 32 bits.

Maximum d'énergie
la source
2

bash utilise un entier 64 bits. Donc, si vous augmentez après que la variable ait atteint son nombre maximum, la variable débordera. Ci-dessous est mon test avec un entier non signé et un entier signé.

MAX_UINT = 18446744073709551615
MAX_INT = 9223372036854775807

$ printf "%llu\n" $((2**64))
0
$ printf "%llu\n" $((2**64-1))
18446744073709551615

$ printf "%lld\n" $((2**63-1))
9223372036854775807
$ printf "%lld\n" $((2**63))
-9223372036854775808
$ printf "%lld\n" $((2**64-1))
-1
PT Huynh
la source
2
veuillez ajouter du texte expliquant comment cela répond à la question. Il semble que vous essayez de démontrer les limites supérieures via du code - pouvez-vous expliquer pourquoi ce code atteindra le résultat requis?
Sir Adelaide