Jaka jest maksymalna wartość liczbowej zmiennej powłoki bash?

17

Jestem ciekawy, co się stanie, gdy zmienna numeryczna w bash zostanie zwiększona bez celowego zatrzymania. Jak duża może być liczba? Czy to się przepełni i stanie się ujemne i po prostu będzie rosło wiecznie? Czy w pewnym momencie pęknie i zatrzyma się?

Używam procesora AMD x86_64, ale chętnie usłyszę również odpowiedzi 32-bitowe, po prostu określ, o czym mówisz. Korzystam z Fedory 21 64bit.

Poszukałem daleko i szeroko, ale z jakiegoś dziwnego powodu nie znalazłem tego konkretnego smakołyka. Wygląda na to, że byłaby to podstawowa informacja we wszystkich instrukcjach i tym podobne.

Maksymalna moc
źródło
3
Co powiesz na wydrukowanie niektórych potęg 2 jako przystawki:for i in {0..70}; do echo 2 to the power of $i = $((2**i)); done
mpy
1
Jeśli chcesz dużych liczb, możesz przełączyć na ksharytmetyki zmiennoprzecinkowe, a nie na liczby całkowite, takie jak bash: ksh -c 'echo $((2**1023))'8.98846567431157954e+307
jlliagre
Będę pamiętać o ksh, jeśli potrzebuję zmiennoprzecinkowego lub wartości w stratosferze, zmiennoprzecinkowy może być całkiem użyteczny. Ale to pytanie jest po prostu dlatego, że znam granice mojego systemu, nie dlatego, że muszę przekraczać granice. Zrobię coś, co sugeruje mpy, nie zacząłem od, ponieważ nie chciałem ryzykować awarii systemu.
Max Power

Odpowiedzi:

22

Może sprowadzać się do twojej wersji bash, systemu operacyjnego i architektury procesora. Dlaczego nie spróbujesz tego sam? Ustaw zmienną na (2 ^ 31) -1, następnie zwiększ ją, ustaw na 2 ^ 32, następnie zwiększ ją, ustaw na 2 ^ 64, a następnie zwiększ ją itd.

Tutaj właśnie wypróbowałem to sam na moim Core i7 Mac z systemem OS X „El Capitan” 10.11.3 i wygląda na to, że bash używa 64-bitowych liczb całkowitych ze znakiem.

$ uname -a
Darwin Spiff.local 15.3.0 Darwin Kernel Wersja 15.3.0: Czw 10 grudnia 18:40:58 PST 2015; root: xnu-3248.30.4 ~ 1 / RELEASE_X86_64 x86_64
$ bash --version
bash --version
GNU bash, wersja 3.2.57 (1) - wydanie (x86_64-apple-darwin15)
Prawa autorskie (C) 2007 Free Software Foundation, Inc.
$
$ ((X = 2 ** 16)); echo $ X
65536 <- w porządku, przynajmniej UInt16
$ ((X = 2 ** 32)); echo $ X
4294967296 <- w porządku, przynajmniej UInt32
$ ((X = 2 ** 64)); echo $ X
0 <- ups, nie UInt64
$ ((X = (2 ** 63) -1)); echo $ X
9223372036854775807 <- w porządku, przynajmniej SInt64
$ ((X ++)); echo $ X
-9223372036854775808 <- przepełnione i opakowane ujemne. Musi być SInt64
Spiff
źródło
3

Założyłem pętlę. while return status is 0 increment a variable with addition and print the variable to stdout Rozpocząłem tuż poniżej 2 ^ 31, pozwoliłem mu przejść bez problemu 2 ^ 31 i 2 ^ 32, zatrzymałem go, a następnie ustawiłem wartość początkową na nieco poniżej 2 ^ 63. W wyniku tego płynnie przeszedł z 9,22e18 do -9,22e18 i kontynuował wzrost. (w kierunku zera)

Aby tylko sprawdzić, czy while [ $? -eq 0 ]faktycznie używałem statusu wyjścia poleceń w pętli while, nie używając statusu wyjścia poprzedniego skryptu lub jakiejś dziwności, uruchomiłem go również z dodatkową komendą wewnątrz pętli zaprojektowaną do utworzenia niezerowego wyjścia status przy poszczególnych przyrostach.

Więc jest podpisany, przewróci się, a nie zatrzyma na maksymalnej wartości, i robi to bez żadnego komunikatu o błędzie. Możliwe jest więc, że skończy się w naprawdę nieskończonej pętli. Nie ogranicza 64-bitowego sprzętu i 64-bitowego systemu Linux do starego 16 lub 32-bitowego standardu.

Maksymalna moc
źródło
2

bash używa 64-bitowej liczby całkowitej. Jeśli więc zwiększysz wartość po osiągnięciu maksymalnej liczby, zmienna przepełni się. Poniżej znajduje się mój test z liczbą całkowitą bez znaku i liczbą całkowitą ze znakiem.

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
źródło
2
proszę dodać tekst wyjaśniający, w jaki sposób odpowiada to pytanie. Wygląda na to, że próbujesz wykazać górne limity za pomocą kodu - czy możesz wyjaśnić, dlaczego ten kod osiągnie wymagany wynik?
Sir Adelaide,