Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

This is an exploration question, meaning I'm not completely sure what this question is about, but I think it's about the biggest integer in Bash. Anyhow, I'll define it ostensively.

$ echo $((1<<8))
256

I'm producing an integer by shifting a bit. How far can I go?

$ echo $((1<<80000))
1

Not this far, apparently. (1 is unexpected, and I'll return to it.) But,

$ echo $((1<<1022))
4611686018427387904

is still positive. Not this, however:

$ echo $((1<<1023))
-9223372036854775808

And one step further afield,

$ echo $((1<<1024))
1

Why 1? And why the following?

$ echo $((1<<1025))
2
$ echo $((1<<1026))
4

Would someone like to analyse this series?

UPDATE

My machine:

$ uname -a
Linux tomas-Latitude-E4200 4.4.0-47-generic #68-Ubuntu SMP Wed Oct 26 19:39:52 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
share|improve this question
    
-9223372036854775808 = 0xF333333333333334. That's a funny-looking edge case. Of course, 4611686018427387904 = 0x4000000000000000. I suspect you are hitting some kind of wraparound on the number of bits to shift by. Why are you doing this, anyway? – Michael Kjörling 3 hours ago
2  
@MichaelKjörling For amusement ;-p – tomas 3 hours ago
up vote 10 down vote accepted

Bash uses intmax_t variables for arithmetic. On your system these are 64 bits in length, so:

$ echo $((1<<62))
4611686018427387904

which is

100000000000000000000000000000000000000000000000000000000000000

in binary (1 followed by 62 0s). Shift that again:

$ echo $((1<<63))
-9223372036854775808

which is

1000000000000000000000000000000000000000000000000000000000000000

in binary (63 0s), in two's complement arithmetic.

To get the biggest representable integer, you need to subtract 1:

$ echo $(((1<<63)-1))
9223372036854775807

which is

111111111111111111111111111111111111111111111111111111111111111

in binary.

If you shift again from -9223372036854775808, the shift wraps around: the left-most digit (1) "falls off" the end and is put back in from the right:

$ echo $((1<<64))
1

This repeats every 64 shifts:

$ echo $((1<<128))
1
$ echo $((1<<192))
1

etc. You can think of shift arithmetic as modulo 64, which explains the results you're seeing: $((1<<1025)) is $((1<<1)), $((1<<1026)) is $((1<<2))...

You'll find the type definitions and maximum values in stdint.h; on your system:

/* Largest integral types.  */
#if __WORDSIZE == 64
typedef long int                intmax_t;
typedef unsigned long int       uintmax_t;
#else
__extension__
typedef long long int           intmax_t;
__extension__
typedef unsigned long long int  uintmax_t;
#endif

/* Minimum for largest signed integral type.  */
# define INTMAX_MIN             (-__INT64_C(9223372036854775807)-1)
/* Maximum for largest signed integral type.  */
# define INTMAX_MAX             (__INT64_C(9223372036854775807))
share|improve this answer
1  
No, you need them, Binary - has higher precedence than <<. – cuonglm 3 hours ago
1  
@cuonglm huh, serves me right for testing on zsh... Thanks again! – Stephen Kitt 3 hours ago
    
@cuonglm and Stephen. Well, that's a good edit. echo $((1<<63-1)) gives me 4611686018427387904. – tomas 3 hours ago
    
@tomas yup, bash uses C operator precedence, zsh has its own by default where $((1<<63-1)) equals $(((1<<63)-1)). – Stephen Kitt 3 hours ago
    
This is good to know, a good question and a very thourough answer, thanks to you both Stephen Kitt and tomas. – Valentin B. 3 hours ago

From the CHANGES file for bash 2.05b:

j. The shell now performs arithmetic in the largest integer size the machine supports (intmax_t), instead of long.

On x86_64 machines intmax_t corresponds to signed 64-bits integers. So you get meaningful values between -2^63 and 2^63-1. Outside that range you just get wrap-arounds.

share|improve this answer
    
Nitpick: between -2^63 and 2^63-1, inclusive. – Nominal Animal 3 hours ago
    
@NominalAnimal True, thank you. – Sato Katsura 3 hours ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.