-1

If I want to set the 37th bit of a long to 1, I believe my code would look something like this:

long l = 0;
l |=  0b1 << 37;

However, this doesn't work because a long cannot shift by more than 31 bits. This confuses me because Oracle documentation says longs are 64 bit. (https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html)

I have taken a look at How do I bit shift a long by more than 32 bits?, but this seems to only work of c/c++.

I want to be able to toggle bits for a data type that has 64 bits. How would I do that in java?

  • 6
    `0b1` isn't a `long`. `0b1L` is – phuclv Jul 27 '21 at 00:41
  • Why shift instead of just setting it with a bitwise OR (clearing with a bitwise AND)? Or either with an XOR? – Dave Newton Jul 27 '21 at 00:43
  • 1
    @DaveNewton - Because some people think it is clearer. – Stephen C Jul 27 '21 at 00:45
  • @DaveNewton The OR is not even needed. Just assigning `l = 0b1L<<37` would be sufficient given the target started out as zero. But imo, if `l` contained some value, this would be less error prone than specifying the `hex` equivalent or even worse, the `binary` equivalent. It says, set the 37th bit where the LSB is bit 0. – WJS Jul 27 '21 at 01:54
  • @WJS YMMV. I almost always prefer hex constants, but I understand why some people prefer things that eventually read as “Bit 8”. You said “toggle”, which shifting won’t do in a *general* way—I go for the general case because I do a lot of bit-fiddling. – Dave Newton Jul 27 '21 at 01:57
  • @DaveNewton I understand. For several years all I did was program in assembly language (the old Digital PDP series). We all have our ways of doing it. – WJS Jul 27 '21 at 01:59
  • 1
    @WJS We had a PDP-9 in the basement at college we ended up restoring and using. 18-bit ftw. – Dave Newton Jul 27 '21 at 02:01

2 Answers2

3
long l;
        
l = 0;
l |= 0b1 << 37;
System.out.println(l);
// Outputs 32
        
l = 0;
l |= 0b1L << 37;
System.out.println(l);
// Outputs 137438953472
enzo
  • 9,861
  • 3
  • 15
  • 38
  • 1
    Answers with zero context get this many upvotes? This is not what good SO answers look like. – rzwitserloot Jul 27 '21 at 01:01
  • 1
    @rswitserloot That's your opinion. The [tour](https://stackoverflow.com/tour) says. *Accepting doesn't mean it's the best answer, it just means that it worked for the person who asked.* You should take a look at the tour to see some of their examples which are one sentence with minimal content that have a similar number of upvotes. I agree that some explanation would have helped. But it doesn't take much to explain the OP was shifting an `int` and not a `long`. – WJS Jul 27 '21 at 01:23
1

The problem you're running into is that your operation breaks down like this:

l |= 0b1 << 37;

Turns into, in sequence:

int _temp = 1 << 37;
l |= (long) _temp;

The reason it's like that is because 0b1, or any numeric literal that lacks a decimal part and a trailing letter to indicate what kind of literal you want (D/F/L for double/float/long), is therefore an int, period. You then left-shift this int value (1; 0b1 is just a weird way to write 1 after all) by 37. The spec of left-shift states that the right-hand operator of a shift operation only considers the lower 5 bits for int shifts and the lower 6 for long shifts. Because otherwise you'd just be making the value 0. Thus, someInt << 37 is a weird way of writing someInt << 5.

The solution is to make sure that your shift operation is actually happening on longs. There are many, many ways to make that happen.

Use a long literal

By writing a trailing L. It can be written in either case, but style guides and developers will egg your house if you use a lowercase l because duh that is incredibly stupid, don't do that. It looks like a 1. Thus:

l |= 1L << 37; // or if you must, 0b1L works too

One step at a time.

long temp = 1;
temp <<= 37;
l |= temp;

Cast it

l |= ((long) 0b1) << 37;

These will all get the job done: They all end up having the << operation be in 'long mode' (which occurs if the LHS is of type long, which it is, in all these 3 examples).

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72