What is the maximum value of a numeric bash shell variable?

Solution 1:

It may come down to your version of bash, your OS, and your CPU architecture. Why don't you try it yourself? Set a variable to (2^31)-1, then increment it, set it to 2^32, then increment it, set it to 2^64, then increment it, etc.

Here, I just tried it myself on my Core i7 Mac running OS X "El Capitan" v10.11.3, and it looks like bash is using signed 64-bit integers.

$ uname -a
Darwin Spiff.local 15.3.0 Darwin Kernel Version 15.3.0: Thu Dec 10 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, at least UInt16
$ ((X=2**32)); echo $X
4294967296                   <-- okay, at least UInt32
$ ((X=2**64)); echo $X
0                            <-- oops, not UInt64
$ ((X=(2**63)-1)); echo $X
9223372036854775807          <-- okay, at least SInt64
$ ((X++)); echo $X
-9223372036854775808         <-- overflowed and wrapped negative. Must be SInt64

Solution 2:

I set up a loop. while return status is 0 increment a variable with addition and print the variable to stdout I started it just under 2^31, I let it pass both 2^31 and 2^32 with no issue, stopped it, then set the initial value to just under 2^63. The result was that it seamlessly rolled over from 9.22e18 to -9.22e18 and continued to increment positively. (toward zero)

Just to check that my while [ $? -eq 0 ] was actually using the exit status of the commands within the while loop, not using the exit status of the previous script or some oddity, I also ran it with an extra command inside the loop designed to create a non zero exit status at particular increments.

So it is signed, it will roll over rather than stop at max value, and it does so without any error message. So it is possible to end up in a truly infinite loop. It does not limit the 64bit hardware and 64bit linux OS to an old 16 or 32bit standard.

Solution 3:

bash use 64-bit integer. So if you increase after variable reaching its max number, variable will overflow. Below is my test with unsigned int and signed integer.

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