Java >>和>>>按位移位运算符

本文深入探讨Java中的位移运算符>>和>>>,解释算术右移和逻辑右移的区别,通过示例说明如何在正数和负数上应用这些运算符,以及它们在不同位数上的表现。

在编程中,按位移位运算符>>表示算术右移>>>表示逻辑右移 ,其差为:

  • >> ,它在右移n位(扩展符号)后保留符号(正数或负数)。
  • >>> ,它会在右移n位(零扩展)后忽略符号。

要使用按位移位运算符>>>>> 。 首先,我们需要知道Java如何使用二进制补码来表示有符号数(正数和负数)。

1. Java和Two的补语。

Java使用二进制补码来表示带符号的数字(正数和负数)。 在下面的示例中,我们将向您展示如何用二进制补码表示正数和负数。

注意
在二进制补码中,左第一位(最高有效位)代表符号,0是正数,1是负数

1.1例如2和-2

2的二进制格式是0000 0010

0000 0010

-2(二进制补码)的二进制格式是1111 1110

0000 0010 (positive 2)
  1111 1101 (invert bits)
  1111 1110 (add 1)
  1111 1110 (-2 in binary)

1.2另一个示例19和-19

19的二进制格式是0001 0011

0001 0011

-19的二进制格式是1110 1101

0001 0011 (positive 19)
  1110 1100 (invert bits)
  1110 1101 (add 1)
  1110 1101 (-19 in binary)

2.算术右移>>或带符号的扩展名。

算术右移>>或带符号的右移保留位移位后的符号(正数或负数)。 此>>运算符使用原始的最高有效位(左侧的第一位)填充所有左侧的空白位置。

算术右移

PS照片从Wikipedia复制。

2.1例如,以8位为数字19,然后算术右移2位19 >> 2

19         = |0001 0011|
                >> 2
19 >> 2    = |??00 0100|11

在上面的示例中,最后2位11从8位中移出了,但是我们应该在左边的前两个空白位置填充什么呢?

答案取决于原始的最高有效位(msb)。 在此示例中,原始msb为0,我们填写?? 与0。

19         = |{0=msb}001 0011|
                >> 2
19 >> 2    = |??00 0100|11
19 >> 2    = |0000 0100|11

2.2另一个例子,用8位数字-19,我们算术右移2位-19 >> 2

-19        = |1110 1101|
                >> 2
-19 >> 2   = |??11 1011|01

在上面的示例中,原始msb为1,我们填充了??11

-19        = |{1=msb}110 1101|
                >> 2
-19 >> 2   = |??11 1011|01
-19 >> 2   = |1111 1011|01

同样,以二进制补码形式,左边的第一位(msb)表示符号,0是正数,1是负数。 复制原始最高有效位(msb)以填充空位的概念将在移位后保留符号-有符号扩展名


问:等等, -19 >> 2的答案是什么?
答:答案是1111 1011-5

这就是二进制补数对负数起作用的方式。

1111 1011 (this is a negative number)
  1111 1010 (sub 1)
  0000 0101 (invert bits)
  0000 0101 (1x2^0 + 1x2^2 = 5)

在二进制补码中,左边的第一位为1表示否定,答案为-5。

3.逻辑右移>>>或零扩展。

>>>逻辑右移忽略该符号,并用零填充所有左边的空白位置。

逻辑右移

PS照片从Wikipedia复制。

3.1例如,以8位为数字19,我们将逻辑右移2位19 >>> 2

19         = |0001 0011|
                >>> 2
19 >>> 2   = |??00 0100|11
19         = |0001 0011|
                >>> 2
19 >>> 2   = |0000 0100|11

3.2对于负数-19,它是相同的。 无论什么条件,逻辑右移都将用零填充左空白位置,而忽略符号。

-19        = |1110 1101|
                >>> 2
-19 >>> 2  = |??11 1011|01
-19        = |1110 1101|
                >>> 2
-19 >>> 2  = |0011 1011|01


问:再等等, -19 >>> 2的答案是什么?

对于8位。 答案是59。

0011 1011 (positive number)
  0011 1011 (1x2^0) + (1x2^1) + (1x2^3) + (1x2^4) + (1x2^5)
  0011 1011 (1 + 2 + 8 + 16 + 32) = 59

在Java中,整数是32位4字节。 答案是1073741819。

System.out.println(-19>>>2); // 1073741819

在Java中, -19 ,将其转换为二进制。

Input -19  = 11111111|11111111|11111111|11101101
-19 >> 2   = 11111111|11111111|11111111|11111011  = -5
-19 >>> 2  = 00111111|11111111|11111111|11111011  = 1073741819

这些按位运算符>>>或>>有什么用例? 请发表评论,谢谢。

注意
如果您发现任何错误或错字,特别是二进制格式,请发表评论并让我知道🙂

4.二进制格式的Java Print Integer。

这是Java程序,使用Integer.toBinaryString以Binary格式打印Integer

ByteSign.java
package com.mkyong.crypto.bytes;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class ByteSign {

    public static final String OUTPUT_FORMAT = "%32s";

    public static void main(String[] args) {

        String STRING_FORMAT = "%-10s = %s";

        int number = 24;

        System.out.println("Positive Number");
        System.out.println(String.format(STRING_FORMAT, "Input " + number, printBinary(number)));
        System.out.println(String.format(STRING_FORMAT, number + " >> 2", printBinary(number >> 2)));      
        System.out.println(String.format(STRING_FORMAT, number + " >>> 2", printBinary(number >>> 2)));

        int number2 = -19;

        System.out.println("\nNegative Number");
        System.out.println(String.format(STRING_FORMAT, "Input " + number2, printBinary(number2)));
        System.out.println(String.format(STRING_FORMAT, number2 + " >> 2", printBinary(number2 >> 2)));
        System.out.println(String.format(STRING_FORMAT, number2 + " >>> 2", printBinary(number2 >>> 2)));

    }

    public static String printBinary(int number) {
        return printBinary(number, 8, "|");
    }

    public static String printBinary(int number, int blockSize, String separator) {

        // pad leading zero
        String pBinary = String
                .format(OUTPUT_FORMAT, Integer.toBinaryString(number))
                .replace(" ", "0");

        // split by blockSize
        List<String> result = new ArrayList<>();
        int index = 0;
        while (index < pBinary.length()) {
            result.add(pBinary.substring(index, Math.min(index + blockSize, pBinary.length())));
            index += blockSize;
        }

        return result.stream().collect(Collectors.joining(separator));
    }
}

输出量

Terminal
Positive Number
Input 24   = 00000000|00000000|00000000|00011000
24 >> 2    = 00000000|00000000|00000000|00000110
24 >>> 2   = 00000000|00000000|00000000|00000110

Negative Number
Input -19  = 11111111|11111111|11111111|11101101
-19 >> 2   = 11111111|11111111|11111111|11111011
-19 >>> 2  = 00111111|11111111|11111111|11111011

参考文献

翻译自: https://mkyong.com/java/java-and-bitwise-shift-operator/

<think>我们之前讨论的是C语言中的箭头运算符(->),现在用户询问的是右移位运算符(>>)。根据用户提供的引用,右移位运算符(>>)在多种编程语言中都有定义,包括Python、Java等。用户特别要求了解右移位运算符>>的详细介绍。 我将按照以下结构回答: 1. 定义:右移位运算符>>的基本定义。 2. 数学原理:解释其数学意义(除以2的幂)。 3. 语法操作规则:如何进行操作,包括操作数类型移位规则。 4. 示例:在不同语言中的示例(主要使用C语言,但也可以参考用户提供的PythonJava示例)。 5. 注意事项:特别是关于有符号数无符号数的区别,以及在不同语言中的行为差异。 6. 常见应用场景。 注意:用户要求使用中文,并且所有数学表达式使用$...$格式(行内)或$$...$$(独立公式)。 另外,根据用户提供的引用[1][2][3][4],我们可以知道: - 右移运算符是将二进制数向右移动指定数。 - 对于无符号数,高补0;对于有符号数,不同语言处理方式不同(C语言中对于有符号数,通常使用算术右移,即高补符号;而Java有>>>运算符进行逻辑右移,高补0)。 但是,用户的问题并没有指定语言,但结合上下文(之前讨论C语言)问题中的引用(涉及PythonJava),我将以C语言为主,同时对比其他语言。 下面开始组织回答。 </think>### 右移位运算符 `>>` 的详解 右移位运算符 `>>` 是运算符的一种,用于将二进制数向右移动指定数。其核心原理是对数据的二进制表示进行移操作,数学等价于**除以 $2^n$($n$ 为移动数)** 并向下取整[^1][^2][^4]。 #### 1. **基本定义与数学原理** 设操作数为 $a$,移位数为 $n$: $$ a >> n = \left\lfloor \frac{a}{2^n} \right\rfloor $$ 其中 $\left\lfloor \cdot \right\rfloor$ 表示向下取整。例如: $$ 12 >> 2 = \left\lfloor \frac{12}{4} \right\rfloor = 3 $$ #### 2. **操作规则** - **无符号整数**:高补 $0$,低溢出丢弃。 $$ \text{例如:} 16 >> 2 = \frac{16}{4} = 4 $$ - **有符号整数**(C/Python/Java等): - 正数:高补 $0$(逻辑右移) - 负数:高补 $1$(算术右移),保持符号不变[^3][^4]。 $$ \text{例如:} (-8) >> 2 = \frac{-8}{4} = -2 $$ #### 3. **二进制操作示例** | 十进制 | 二进制(8) | 操作 | 结果(二进制) | 结果(十进制) | |--------|--------------|------|----------------|----------------| | 12 | `00001100` | `>> 2` | `00000011` | 3 | | 16 | `00010000` | `>> 2` | `00000100` | 4 | | -8 | `11111000` | `>> 2` | `11111110` | -2 | #### 4. **编程语言实现** **C语言示例**: ```c #include <stdio.h> int main() { int a = 12; printf("%d >> 2 = %d\n", a, a >> 2); // 输出:3 return 0; } ``` **Java/Python 对比**: - Java 提供逻辑右移 `>>>`(高补 $0$)与算术右移 `>>`(高补符号)[^2]。 - Python 的 `>>` 行为与 C 语言算术右移一致。 #### 5. **关键注意事项** 1. **移位数限制**: 若 $n$ 超过数据类型数(如 `int` 为 $32/64$ ),结果未定义(C语言)或取模运算(Java)。 2. **负数右移**: 结果依赖语言规范(如 C 标准未强制规定,但主流编译器均用算术右移)。 3. **小数移位**: 仅适用于整数类型,浮点数需转换为整数再操作。 #### 6. **应用场景** - **高效除法**:$a >> n$ 比 $a / 2^n$ 更快(硬件级优化)。 - **数据压缩**:如存储颜色值(RGB $24$ → RGB $16$ )。 - **掩码提取**: ```c int color = 0xFFA07B; // RGB 颜色值 int red = (color >> 16) & 0xFF; // 提取红色分量 ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值