简体   繁体   中英

Why do we need to use shift operators in java?

  1. What is the purpose of using Shift operators rather than using division and multiplication?

  2. Are there any other benefits of using shift operators?

  3. Where should one try to use the shift operator?

Division and multiplication are not really a use of bit-shift operators. They're an outdated 'optimization' some like to apply.

They are bit operations, and completely necessary when working at the level of bits within an integer value.

For example, say I have two bytes that are the high-order and low-order bytes of a two-byte (16-bit) unsigned value. Say you need to construct that value. In Java, that's:

int high = ...;
int low = ...;
int twoByteValue = (high << 8) | low;

You couldn't otherwise do this without a shift operator.

To answer your questions: you use them where you need to use them! and nowhere else.

The shift operator is used when you're performing logical bits operations, as opposed to mathematical operations.

It can be used for speed, being significantly faster than division/multiplication when dealing with operands that are powers of two, but clarity of code is usually preferred over raw speed.

It is useful in constructing values which are a combination of numbers, where bits are grouped as different values themselves. (Sean Owen's answer explains this better.)

For example, working with colours which are:

  • "#AARRGGBB" as a base16 string
  • 0xAAAARRRRGGGGBBBB as an integer

In its integer format, you can use shift to get the actual value of a component of the integer as a usable number.

public static int stringToColor(String s) throws JSExn {
    // string starts with '#' - parse integer from string
    try {
        // used to build up the return value
        int a, r, g, b;

        switch (s.length()) {
        case 4:
            a = 0xFF000000;
            r = Integer.parseInt(s.substring(1, 2), 16);
            r = r << 16 | r << 20;
            b = Integer.parseInt(s.substring(2, 3), 16);
            b = b << 8 | b << 12;
            g = Integer.parseInt(s.substring(3, 4), 16);
            g = g | g << 4;
            break;
        case 5:
            a = Integer.parseInt(s.substring(1, 2), 16);
            a = a << 24 | a << 28;
            r = Integer.parseInt(s.substring(2, 3), 16);
            r = r << 16 | r << 20;
            b = Integer.parseInt(s.substring(3, 4), 16);
            b = b << 8 | b << 12;
            g = Integer.parseInt(s.substring(4, 5), 16);
            g = g | g << 4;
            break;
        case 7:
            a = 0xFF000000;
            r = Integer.parseInt(s.substring(1, 3), 16) << 16;
            b = Integer.parseInt(s.substring(3, 5), 16) << 8;
            g = Integer.parseInt(s.substring(5, 7), 16);
            break;
        case 9:
            a = Integer.parseInt(s.substring(1, 3), 16) << 24;
            r = Integer.parseInt(s.substring(3, 5), 16) << 16;
            b = Integer.parseInt(s.substring(5, 7), 16) << 8;
            g = Integer.parseInt(s.substring(7, 9), 16);
            break;
        default:
            throw new JSExn("Not a valid color: '"+s+"'");
        }

        // return our integer ARGB
        return a | r | b | g;
}

Strength reduction occurs when an operation is replaced by an equivalent operation that executes faster.

  1. replacing integer division or multiplication by a power of 2 with an arithmetic shift or logical shift..
  2. replacing integer multiplication by a constant with a combination of shifts, adds or subtracts.
  3. replacing integer division by a constant with a multiplication, taking advantage of the limited range of machine integers.

Why is this wrong?

1.Reduces performance as time required for calculation increases. 2. Arithmetic Operations like division and multiplication are slower. 3. Expensive operations

Benefits

  1. Improves performance.
  2. Faster calculations.

Demerit

  1. Readability of Code decreases.

It is useful when you deal with flags, you could store in just one int variable the information about active flags, see following please:

public class DealingWithShiftOperators {

    public static void main(String[] args) {

        int active_flags = 10;

        printActiveFlags(active_flags);

    }

    public static void printActiveFlags(int active_flags) {

        final int TOTAL_FLAGS = 8;
        final int MAX_VALUE = 1 << TOTAL_FLAGS;
        final int MIN_VALUE = 1;

        int current_flag = MAX_VALUE;

        do {
            current_flag = current_flag >> 1;

            if (active_flags - current_flag < 0) {
                System.out.println(current_flag + ": off");
            } else {
                active_flags = active_flags - current_flag;
                System.out.println(current_flag + ": on");
            }

        } while (current_flag > MIN_VALUE);

    }

}

The above example prints the follow to the output:

128: off
64: off
32: off
16: off
8: on
4: off
2: on
1: off

As you can see, the active_flags are number 2 and number 8. We stored that information in just one variable, its value is 10 (8+2).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM