Bash arithmetic uses signed numbers.
So the quick answer would be:
((MAX=(1<<63)-1))
But since you want your script to not know about the bitness of the system it's running on, then let's keep going.
Brute force would be, keep adding 1 in a loop, until you hit the point where it will overflow unto a negative number. But that could take years! :-) A quicker and more elegant way to do it is with a simple bit-shift.
Let's find the sign bit, i.e., let's find the number that has 1
in the most signifficant bit, and zeros in all the other bits, however many they may be. Once we have that number, we'll simply subtract 1
from it, and we'll get the largest signed number.
# MIN -- the smallest signed number 0x8000...00 (it equals MAX+1)
# MAX -- the largest signed number 0x7Fff...FF <-- what we are looking for
MIN=1; until (( (MIN<<=1) < 0 )) ;do :;done
((MAX=MIN-1))
echo $MAX
Result:
9223372036854775807
Or, here's a one-liner, without a loop. We put the hex representation of a number in a variable, and then mask the sign bit through the variable expantion when passing it to the printf
builtin:
printf -v MAX %x -1 && printf -v MAX %d 0x${MAX/f/7}
echo $MAX
Result:
9223372036854775807
On a machine with a different bitness than mine, the result will be a different number.
And just for illustration, in my case:
printf "MAX %X %d\nMIN %X %d\n" $MAX $MAX $MIN $MIN
MAX 7FFFFFFFFFFFFFFF 9223372036854775807
MIN 8000000000000000 -9223372036854775808
A little side note about MIN: You may want to constrain yourself to using ((MIN=-MAX))
, otherwise you will occasionally run into problems with some arithmetic operations.
((MIN=-MAX)) ; printf "MIN %X %d\n" $MIN $MIN
MIN 8000000000000001 -9223372036854775807
-1
and just masking the most signifficant bit somehow.