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

I'm curious as to what happens when a numeric variable in bash is incremented up without purposely stopping it. How large can the number get? Will it overflow and become negative and just continue to increment forever? Will it break and skid to a stop at some point?

I am using an x86_64 AMD processor, but I would be happy to hear 32bit answers as well, just specify which you are talking about. I am running Fedora21 64bit.

I've googled far and wide but haven't found this specific tidbit for some odd reason. It seems like it would be a basic piece of info in all the manuals and such.

3

5 Answers

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

I set up a loop. while return status is 0 increment a variable with addition and print the variable to stdoutI 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.

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
3

I improved and automated @Spiff 's answer:

MAX_INT=0
for ((x=1,y=1; x<<=y; y<<=1))
do if ((x>0)) then MAX_INT=$x continue fi if (((x=~x)>0)) then MAX_INT=$x fi break
done
echo $MAX_INT

commands to get maximum bash integer (maxI), and minimum bash integer (minI):

$ maxI=$( echo `printf "%u" -1` / 2 | bc )
$ echo $maxI
9223372036854775807
$ minI=$(($maxI + 1))
$ echo $minI
-9223372036854775808

The results in different machines may be different, but the command should be the same.

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like