Advanced Operator-Bitwise

Speaking computer language

Kishore Premkumar
The Startup
7 min readJun 12, 2020

--

Swift provides several advanced operators that perform more complex value manipulation. These include all of the bitwise and bit shifting operators you will be familiar with from C and Objective-C.

Unlike arithmetic operators in C, arithmetic operators in Swift do not overflow by default. Overflow behavior is trapped and reported as an error. To opt in to overflow behavior, use Swift’s second set of arithmetic operators that overflow by default, such as the overflow addition operator (&+). All of these overflow operators begin with an ampersand (&).

Bitwise Operators

A bitwise operator is a character representing an action that works on data at the bit level rather than with byte or larger units of data, as is more common. Bitwise operators can be useful when you work with raw data from external sources, such as encoding and decoding data for communication over a custom protocol.

A bitwise operator works with the binary representation of a number rather than that number’s value. The operand is treated as a set of bits, instead of as a single number.

Swift supports all of the bitwise operators like Bitwise NOT, Bitwise AND, Bitwise OR, Bitwise XOR, Bitwise Left shift and right shift.

Bitwise NOT operator

It is represented by a tilde (~ ) sign and can be applied on a single operand. This inverts all the bits. i.e changes 1 to 0 and 0 to 1.

If X is a variable/constant that holds binary value(0 or 1).

The bitwise NOT(~) operator is a prefix operator, and appears immediately before the value it operates on, without any white space

Example

In the above program, UNint8 is Unsigned int of size 8 bits ( store numbers from only 0 to 255 ). initialBits contains a binary value 1111000 that corresponds to 240 in decimal. To represent the number in binary we need to declare 0b as a prefix. Without 0b as a prefix, it will treat it as a normal integer.

we have used bitwise not operator, it changes all the 1 to 0. So, the constant invertedBits contains 00001111 which is equivalent to 15.

Bitwise AND operator

It is represented by & and can be applied to two operands. The AND operator compares two bits and returns 1 if both bits are 1, otherwise returns 0.

If X and Y is a variable/constant that holds a binary value(0 or 1).

Example

In the above program, the statement let result = firstOperand & secondOperand combines two operands firstOperand AND secondOperand .

String(value, radix: )is used to represent a number in a different format system. If we give radix value 2. It converts the number to binary number system. Like this, we can use 16 for hexadecimal and 8 for decimal.

Bitwise OR operator

It is represented as | and can be applied to two operands. The bitwise OR operator compares two bits and generates a result of 1 if one or more of its inputs are 1 otherwise 0.

If Xand Y are variable/constant that holds binary value (0 or 1).

Example

Bitwise XOR operator

It is represented as ^ and can be applied to two operands. The XOR operator compares two bits and generates a result of 1 if exactly one of its inputs is 1 otherwise it returns 0. (In other words, if both the inputs are the same then output is 0 otherwise it returns 1.)

If x and y are variable/constant that holds binary value i.e 0 or 1.

Example

Bitwise shift for unsigned integers

The bitwise left shift operator (<<) and bitwise right shift operator (>>) move all bits in a number to the left or the right by a certain number of places, according to the rules defined below.

Bitwise left and right shifts have the effect of multiplying or dividing an integer by a factor of two. Shifting an integer’s bits to the left by one position doubles its value, whereas shifting it to the right by one position halves its value.

In simple words, digits get shifted to the left then add 0 to the end digit on the right position or its right shift then add 0 to the starting digit on the left position.

Bitwise left shift operator

  • Denoted by <<
  • Existing bits are moved to the left by the requested number of places.
  • Any bits that are moved beyond the bounds of the integer’s storage are discarded.
  • When shifting left, the most-significant bit is lost, and a 0 bit is inserted on the other end.

Blue numbers are shifted, gray numbers are discarded, and orange zeros are inserted

In the above program, we use << 1 means to shift the bit by 1 to the left. The digits get shifted to the left by one position, and the last digit on the right is filled with a zero.

This returns 11111110 which is equivalent to 254.

Bitwise Right shift operator

  • Denoted by >>
  • Existing bits are moved to the left by the requested number of places.
  • Any bits that are moved beyond the bounds of the integer’s storage are discarded.
  • When shifting right, the least-significant bit is lost and a 0 is inserted on the other end.

Blue numbers are shifted, gray numbers are discarded, and orange zeros are inserted

In the above program, we have used the right shift operator on an unsigned integer. Using >> 1 means to shift the bit by 1 to the right. The digits get shifted to the right by one position, and the first digit on the left is filled with a zero.

This returns 01111111 which is equivalent to 127.

2’s Complement

The compiler used Two complement to represent integers. To get the two’s complement negative notation of an integer, you should first write out the number in binary then invert the digits, and add one to the result.

Steps (e.g:- -4)

  • write 4 in binary form : 00000100
  • Inverts the digits. 0 becomes 1 and 1 becomes 0. (11111011)
  • add 1
    e.g:-
    11111011 changes in a form of 11111100
    -4 is equivalent to 11111100.

But, there is a little twist that compiler made which we did not notice. so, we used keyword like Int8(Bitpattern: binaryValue) now compiler knows given binary value is 2' s complement.

Example

In the above example, the compiler treated the binary number to -4 in decimal only for the Signed 8-Bit Integer. Therefore statement print(Int8(bitPattern: 0b11111100)) outputs -4 in the screen.

Bitwise shift for signed integers

The shifting behavior is more complex for signed integers than for unsigned integers, because of the way signed integers are represented in binary.

Signed integers use their first bit (known as the sign bit)to indicate whether the integer is positive or negative. A sign bit of 0 means positive, and a sign bit of 1 means negative.

The remaining bits (known as the value bits) store the actual value. Positive numbers are stored in the same way as for unsigned integers. (e.g-: -4 is equivalent to 11111100)

This encoding for negative numbers is known as a two’s complement representation. In the above topic, I mentioned how to encode binary value into two’s complement.

when using a bitwise right shift for signed number apply the same rules as for unsigned integers, but fill any empty bits on the left with the sign bit, rather than with a zero.

This action ensures that signed integers have the same sign after they are shifted to the right, and is known as an arithmetic shift. Keeping the sign bit the same during this shift means that negative integers remain negative.

Example (Right shift)

In the above program, -89 is represented as 10100111 in binary. Shifting it one bit to the right and placing 1 in vacant position, returns 11010011 which is equivalent to -45.

Overflow operator

If you try to insert a number into an integer constant or variable that cannot hold that value by default Swift reports an error rather than allowing an invalid value to be created. This behavior gives extra safety when you work with numbers that are too large or too small.

For example, the UInt16 integer type can hold any signed integer between -32768 and 32767. If you trying to set an UInt16 integer outside of this range cause an error.

Swift provides three arithmetic overflow operators. These operators all begin with an ampersand & .

  • Overflow addition (&+)
  • Overflow Subtraction (&-)
  • Overflow Multiplication (&*)

Example 1

In the above program, the maximum value that a UInt8 can hold is 11111111 in binary. If you add1 from 11111111 using the overflow addition operator (&+), the number will overflow and wrap around to 00000000 , or 0 in decimal.

Example 2

In the above program, the minimum value that a UInt8 can hold is zero, or 00000000 in binary. If you subtract 1 from 00000000 using the overflow subtraction operator (&-), the number will overflow and wrap around to 11111111, or 255 in decimal.

--

--