2

Can someone please explain, in very simple, simple terms why we need bitwise operators? I just started programming one month ago.

I understand that everything is stored in binary form. I understand computers count in base 2. And I understand the bitwise operators. I just don't understand what kind of programming would require using bits and bitwise operators?

I tried to look for the answer on the web, and I read something do with binary flags and disabilities, and got even more confused.

I guess I'm just wondering, what kind of real life application would require bits and bitwise operators?

phuclv
  • 37,963
  • 15
  • 156
  • 475
jason adams
  • 545
  • 2
  • 15
  • 30
  • Disabilities? What do you mean? – harold Mar 24 '14 at 10:01
  • So you want to make a variable which only tells you whether something is true or false? Well you could do it the easy way of: var/on = 1 The problem comes when you want to work with something like disabilities. There are many disabilities and having one variable for each disability is both costly in terms of memory used, as well as tedious to work with. To solve such a problem we're going to use binary flags. -- http://baystation12.net/wiki/index.php/Binary_flags – jason adams Mar 25 '14 at 14:57
  • [Are bitwise operations still practical?](https://stackoverflow.com/q/6559657/995714), [Real world use cases of bitwise operators](https://stackoverflow.com/q/2096916/995714) – phuclv May 30 '22 at 15:19
  • Does this answer your question? [Real world use cases of bitwise operators](https://stackoverflow.com/questions/2096916/real-world-use-cases-of-bitwise-operators) – phuclv May 30 '22 at 15:19

3 Answers3

1

You can pack data in a very concise format.

The smallest amount that an x86 computer can adress is a byte - that's 8 bits.

If your application has a 24 yes/no flags (bools), would you store them in 1 byte each? That's 24 bytes of data. If you use bits, then each byte contains 8 of those bools - so you only need 3 bytes for 24 yes/no values:

> 1 Byte per flag:
> 0000 0000 = off
> 0000 0001 = on
> Easy to check: if(b == 0) { /* flag is off */ } else if(b == 1) { /* flag is on */ }

> 1 Bit per flag
> 0011 1101 = Flags 1, 4, 8, 16 and 32 are on, flags 2, 64 and 128 are off
> Packs 8 flags in 1 byte
> Harder to check:
> if( (b & 32) != 0) { /* Flag 32 is on */ }

This is important for network protocols and other systems where every byte really counts.

For general purpose business applications, there is usually no need for the additional complexity, just use 1 byte per flag.

This isn't just used for bools. For example, some applications may want to store two numbers than can go from 0-15 - an example is the Commodore 64 which really needed to conserve RAM wherever possible. One byte can hold two of those numbers:

> Instead of interpreting this as 8 bits (ranging from 1 to 128)
> this is really two 4 bit numbers:
> 1001 0110
> First Number: 1001 = 1 + 8 = 9
> Second Number: 0110 = 2 + 4 = 6
>
> Getting the first number requires a bit shift to move them into position:
> (b >> 4) turns the above number into this:
> 0000 1001 - this can now be simply cast as a byte and returns 9
>
> The second number requires us to "turn off" the first 4 bits
> We use the AND operator for this: b = (b & 15)
> 15 in decimal is 0000 1111 in binary.
>
> 1001 0110 AND
> 0000 1111 =
> 0000 0110
>
> Once again, the result can be interpreted as a byte and results in the number 6

One more really neat trick is to quickly check if a number is even or odd. An odd number always has the lowest significant bit (the 1 Bit) set, while an even numer always as it clear.

So your check for IsEven looks like this:

return (b & 1) == 0; // Bit 1 not set - number is even

(Note: Depending on the language, Compilers MAY decide to optimize stuff, but in a nutshell, that's it)

Michael Stum
  • 177,530
  • 117
  • 400
  • 535
  • Can you explain why First Number: 1001 is divided as 1+8? is it because 0b1 + 0b1000? and why would we divide 8 bits into 4 bits numbers? is it to save storage? – jason adams Mar 24 '14 at 08:30
  • @user3436782 First Number is an example of how I subdivided an 8-Bit byte (which normally has 128-64-32-16-8-4-2-1 Bits) into 2 4-Bit parts (both 8-4-2-1 8-4-2-1) - this is not something a computer can do, which is why the bit shifting is needed to have the computer interpret it. And yes, the reason is to save space. One example is the DNS Network Protocol, which subdivides 1 byte into a 4 Bit number and 4 boolean flags. It's not common to do that, but if you need to pack as much data as possible into as little space as possible, those tricks emerge. – Michael Stum Mar 24 '14 at 08:41
  • Thanks Michael. I think I have a better idea of what they're used for. Maybe I'll get a firmer grasp once I start to learn more concepts. – jason adams Mar 24 '14 at 08:46
1

Storing state using binary flags allows you to have many "active flags" in one variable, and by accessing it bitwise we can check be binary value of each position. You can also use it to access specific parts of a number if you know how it's stored, here's an example from processing.

I've used it in real life business solutions to store state that is best represented as many related flags. Like proficiency in different kinds of magic :)

Skills:
    None (0)
    Conjuration (1)
    Evocation (2)
    Illusion (4)
    Necromancy (8)
    Alteration (16)

Now I can store what magic wizards are capable of in a single field. If a wizards skills sum up to 13 we know that he knows: Conjuration, Illusion and Necromancy. All of this is easily accessed using bitwise operations. Exploiting what we know about bits and base-2 we can use each bit in a number as a boolean flag, usually to store some kind of related state (like options or magic proficiency, in C# the FlagsAttribute is very helpful.

Zache
  • 1,023
  • 6
  • 14
0

well...there are a number of instances where you might use bitwise operators. Here's one. The linux system call takes a file path name and a bitmask that specifies the access mode for the file as arguments. Examples: open("somefile", O_RDWR | O_CREAT | O_TRUNC | S_IWUSR), open("somefile", O_RDONLY). The bitwise or operation allows us to specify a lot of information in a single argument, and therefore simplifies the interface to the kernel.

Wcrousse
  • 203
  • 2
  • 10