Was ist der Maximalwert einer numerischen Bash-Shell-Variablen?


17

Ich bin gespannt, was passiert, wenn eine numerische Variable in Bash erhöht wird, ohne sie absichtlich anzuhalten. Wie groß kann die Zahl werden? Wird es überlaufen und negativ werden und sich für immer erhöhen? Wird es brechen und irgendwann zum Stillstand kommen?

Ich verwende einen x86_64 AMD-Prozessor, würde mich aber auch über 32-Bit-Antworten freuen. Geben Sie einfach an, um welche es sich handelt. Ich verwende Fedora21 64bit.

Ich habe weit und breit gegoogelt, aber aus irgendeinem Grund keinen bestimmten Leckerbissen gefunden. Es scheint, als wäre es eine grundlegende Information in allen Handbüchern und dergleichen.


3
Wie wäre es mit dem Ausdruck von Zweierpotenzen als Starter:for i in {0..70}; do echo 2 to the power of $i = $((2**i)); done
mpy 22.01.16

1
Wenn Sie große Zahlen wollen, können Sie auf kshGleitkomma-Arithmetik umschalten , nicht auf Ganzzahl-Arithmetik wie bash: ksh -c 'echo $((2**1023))'8.98846567431157954e+307
jlliagre

Ich werde ksh im Hinterkopf behalten, wenn ich Fließkommazahlen oder Werte in der Stratosphäre benötige. Fließkommazahlen können sehr nützlich sein. Aber diese Frage ist einfach so, dass ich die Grenzen meines Systems kenne, es liegt nicht daran, dass ich seine Grenzen überschreiten muss. Ich werde so etwas tun, wie es mpy vorschlägt. Ich wollte es nicht, weil ich nicht riskieren wollte, einen Systemabsturz zu verursachen.
Max Power

Antworten:


22

Dies hängt möglicherweise von Ihrer Version von bash, Ihrem Betriebssystem und Ihrer CPU-Architektur ab. Warum versuchst du es nicht selbst? Setzen Sie eine Variable auf (2 ^ 31) -1, erhöhen Sie sie dann, setzen Sie sie auf 2 ^ 32, erhöhen Sie sie dann, setzen Sie sie auf 2 ^ 64, erhöhen Sie sie dann usw.

Hier habe ich es gerade selbst auf meinem Core i7 Mac unter OS X "El Capitan" v10.11.3 versucht, und es sieht so aus, als ob bash signierte 64-Bit-Ganzzahlen verwendet.

$ uname -a
Darwin Spiff.local 15.3.0 Darwin Kernel Version 15.3.0: Do 10. Dezember 18:40:58 PST 2015; root: 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)); echo $ X
65536 <- okay, zumindest UInt16
$ ((X = 2 ** 32)); echo $ X
4294967296 <- Okay, mindestens UInt32
$ ((X = 2 ** 64)); echo $ X
0 <- oops, nicht UInt64
$ ((X = (2 ** 63) -1)); echo $ X
9223372036854775807 <- okay, mindestens SInt64
$ ((X ++)); echo $ X
-9223372036854775808 <- Negativ übergelaufen und umwickelt. Muss SInt64 sein

3

Ich habe eine Schleife aufgebaut. while return status is 0 increment a variable with addition and print the variable to stdout Ich habe es gerade unter 2 ^ 31 gestartet, habe es ohne Probleme 2 ^ 31 und 2 ^ 32 passieren lassen, habe es gestoppt und dann den Anfangswert auf knapp 2 ^ 63 gesetzt. Das Ergebnis war, dass es nahtlos von 9.22e18 auf -9.22e18 überging und sich weiterhin positiv erhöhte. (gegen null)

Nur um zu überprüfen, ob my while [ $? -eq 0 ]tatsächlich den Exit-Status der Befehle in der while-Schleife verwendet, nicht den Exit-Status des vorherigen Skripts oder eine Kuriosität, habe ich es auch mit einem zusätzlichen Befehl in der Schleife ausgeführt, der einen Exit ungleich Null erstellen soll Status in bestimmten Schritten.

Wenn es also signiert ist, wird ein Rollover ausgeführt, anstatt beim Maximalwert anzuhalten, und dies ohne Fehlermeldung. So ist es möglich, in einer Endlosschleife zu enden. Es beschränkt die 64-Bit-Hardware und das 64-Bit-Linux-Betriebssystem nicht auf einen alten 16- oder 32-Bit-Standard.


2

Bash verwenden 64-Bit-Ganzzahl. Wenn Sie also nach Erreichen der maximalen Anzahl der Variablen eine Erhöhung vornehmen, läuft die Variable über. Unten ist mein Test mit Int und Integer mit Vorzeichen.

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

2
Bitte fügen Sie einen Text hinzu, in dem erläutert wird, wie diese Frage beantwortet wird. Es sieht so aus, als würden Sie versuchen, die Obergrenzen per Code zu demonstrieren. Können Sie erklären, warum dieser Code das erforderliche Ergebnis erzielt?
Sir Adelaide
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.