欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java二進(jìn)制運(yùn)算符超詳細(xì)講解及擴(kuò)展知識

 更新時(shí)間:2025年09月11日 09:53:43   作者:彌鴻  
Java源碼中涉及到大量的二進(jìn)制操作,非常的復(fù)雜,但非常的快速,下面這篇文章主要介紹了Java二進(jìn)制運(yùn)算符超詳細(xì)講解及擴(kuò)展知識的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

看Java數(shù)據(jù)結(jié)構(gòu)源碼的時(shí)候發(fā)現(xiàn)很多源碼中都用到了<<>>運(yùn)算符,果然是我太low了,用運(yùn)算符都跟不上大佬的腳步;所以打算從頭再看一次這些Java中的運(yùn)算符;

本來像寫的簡單點(diǎn)的,但是一開始梳理就收不住了… 然后就又扯出來了一大堆知識點(diǎn)…

經(jīng)過我個(gè)人的學(xué)習(xí)過程,梳理了一下相關(guān)的知識:

  • 計(jì)算機(jī)存儲單元
  • 原碼、反碼、補(bǔ)碼、掩碼
  • 基本數(shù)據(jù)類型
  • 整數(shù)的存儲

計(jì)算機(jī)存儲單元

首先區(qū)分兩個(gè)概念:

  • 最小信息單元:比特(bit,二進(jìn)制位)是計(jì)算機(jī)中表示信息的最小單位,對應(yīng)二進(jìn)制中的一個(gè) “0” 或 “1”。
  • 最小存儲單元:字節(jié)(byte)是計(jì)算機(jī)硬件中用于存儲數(shù)據(jù)的最小可尋址(可獨(dú)立操作)單元,通常由 8 個(gè)比特組成(1 byte = 8 bit)

1B = 8bit;
1KB = 1024B;
1MB = 1024KB;
1GB = 1024MB;
1TB = 1024GB

區(qū)分這個(gè)概念的目的是:為什么二進(jìn)制數(shù)的表示長度只能是8的倍數(shù);(反正我剛學(xué)那會是不懂)

原碼、補(bǔ)碼、反碼、掩碼

一、原碼(True Form)

定義:最直觀的二進(jìn)制表示法,由“符號位+數(shù)值位”組成,直接對應(yīng)十進(jìn)制數(shù)的正負(fù)和絕對值。

  • 規(guī)則
    • 最高位為符號位:0表示正數(shù),1表示負(fù)數(shù);
    • 其余位為數(shù)值位:直接表示該數(shù)的絕對值的二進(jìn)制。
  • 示例(以8位二進(jìn)制為例):
    • 十進(jìn)制+5的原碼:00000101(符號位0,數(shù)值位5的二進(jìn)制0000101);
    • 十進(jìn)制-5的原碼:10000101(符號位1,數(shù)值位同樣是5的二進(jìn)制);
    • 十進(jìn)制0的原碼有兩種:00000000(+0)和10000000(-0)。
  • 特點(diǎn)與問題
    • 優(yōu)點(diǎn):直觀易懂,與十進(jìn)制的對應(yīng)關(guān)系明確;
    • 缺點(diǎn):
      1. 0的表示不唯一(+0和-0),浪費(fèi)存儲空間;
      2. 加減法運(yùn)算復(fù)雜(正數(shù)加負(fù)數(shù)需先比較絕對值,再做減法,符號單獨(dú)處理),不適合計(jì)算機(jī)硬件直接實(shí)現(xiàn)。

二、反碼(One’s Complement)

定義:原碼的“變形”,是從原碼過渡到補(bǔ)碼的中間形式,主要用于簡化負(fù)數(shù)的運(yùn)算。

  • 規(guī)則
    • 正數(shù)的反碼 = 原碼(與原碼完全相同);
    • 負(fù)數(shù)的反碼 = 原碼的“符號位不變,數(shù)值位按位取反”(0變1,1變0)。
  • 示例(8位二進(jìn)制):
    • 十進(jìn)制+5的原碼:00000101 → 反碼:00000101(不變);
    • 十進(jìn)制-5的原碼:10000101 → 反碼:11111010(符號位1不變,數(shù)值位0000101取反為1111010);
    • 十進(jìn)制0的反碼:00000000(+0)和11111111(-0)(仍不唯一)。
  • 特點(diǎn)與問題
    • 優(yōu)點(diǎn):一定程度上簡化了減法運(yùn)算(減法可轉(zhuǎn)化為“加負(fù)數(shù)的反碼”);
    • 缺點(diǎn):
      1. 0的表示仍不唯一;
      2. 運(yùn)算后可能需要“循環(huán)進(jìn)位”(最高位的進(jìn)位需加到最低位),硬件實(shí)現(xiàn)仍復(fù)雜,實(shí)際中很少直接使用。

三、補(bǔ)碼(Two’s Complement)

定義:計(jì)算機(jī)中實(shí)際使用的有符號整數(shù)表示法,解決了原碼和反碼的運(yùn)算缺陷,能將減法統(tǒng)一為加法。

  • 規(guī)則
    • 正數(shù)的補(bǔ)碼 = 原碼(與原碼、反碼相同);
    • 負(fù)數(shù)的補(bǔ)碼 = 反碼 + 1(即“原碼符號位不變,數(shù)值位取反后加1”)。
  • 示例(8位二進(jìn)制):
    • 十進(jìn)制+5的補(bǔ)碼:00000101(與原碼、反碼一致);
    • 十進(jìn)制-5的補(bǔ)碼:
      原碼10000101 → 反碼11111010 → 反碼+1 = 11111011(補(bǔ)碼);
    • 十進(jìn)制0的補(bǔ)碼:00000000(唯一表示,無+0和-0之分)。
  • 核心優(yōu)勢
    1. 0的表示唯一,節(jié)省存儲空間;
    2. 減法可轉(zhuǎn)化為加法:a - b = a + (-b的補(bǔ)碼),硬件只需實(shí)現(xiàn)加法器即可,無需單獨(dú)的減法電路;
    3. 運(yùn)算時(shí)符號位自動參與運(yùn)算,無需單獨(dú)處理符號。
  • 驗(yàn)證:用補(bǔ)碼計(jì)算5 - 3(即5 + (-3)):
    • 5的補(bǔ)碼:00000101
    • -3的補(bǔ)碼:原碼10000011 → 反碼11111100 → 補(bǔ)碼11111101;
    • 相加:00000101 + 11111101 = 100000010(8位截?cái)嗪鬄?code>00000010,即十進(jìn)制2,正確)。

四、掩碼(Mask)

定義:一種特定的二進(jìn)制序列(通常是整數(shù)),通過與位運(yùn)算符(&、|、^)配合,實(shí)現(xiàn)對目標(biāo)二進(jìn)制數(shù)“特定位的提取、設(shè)置或清除”。

  • 核心作用:精準(zhǔn)操作二進(jìn)制中的某幾位,而不影響其他位。
  • 常見用法
    1. 提取特定位(用&運(yùn)算):
      掩碼中需保留的位設(shè)為1,其他位設(shè)為0,與目標(biāo)數(shù)&后,僅保留目標(biāo)數(shù)中對應(yīng)掩碼1的位。
      例:提取8位二進(jìn)制10110101的低4位:
      目標(biāo)數(shù):10110101
      掩碼:00001111(低4位為1)
      結(jié)果:10110101 & 00001111 = 00000101(僅保留低4位)。
    2. 設(shè)置特定位為1(用|運(yùn)算):
      掩碼中需設(shè)置為1的位設(shè)為1,其他位設(shè)為0,與目標(biāo)數(shù)|后,目標(biāo)數(shù)中對應(yīng)掩碼1的位會被強(qiáng)制設(shè)為1。
      例:將8位二進(jìn)制10110101的第5位(從0開始計(jì)數(shù))設(shè)為1:
      目標(biāo)數(shù):10110101(第5位當(dāng)前為0)
      掩碼:00100000(第5位為1)
      結(jié)果:10110101 | 00100000 = 10110101(第5位變?yōu)?)。
    3. 清除特定位(設(shè)為0)(用& ~掩碼運(yùn)算):
      掩碼中需清除的位設(shè)為1,其他位設(shè)為0,先對掩碼取反(~),再與目標(biāo)數(shù)&,目標(biāo)數(shù)中對應(yīng)原掩碼1的位會被設(shè)為0。
      例:清除8位二進(jìn)制10110101的高4位:
      目標(biāo)數(shù):10110101
      掩碼:11110000(高4位為1)
      取反掩碼:00001111
      結(jié)果:10110101 & 00001111 = 00000101(高4位被清除)。
  • 典型應(yīng)用:權(quán)限控制(用位表示不同權(quán)限)、數(shù)據(jù)打包/解包(如協(xié)議報(bào)文解析)、硬件寄存器操作等。

Java的基本數(shù)據(jù)類型

不同基本數(shù)據(jù)類型的區(qū)別在于二進(jìn)制的“組織方式”和“長度”(即占用的比特?cái)?shù)),但本質(zhì)都是二進(jìn)制。以下是具體說明:

一、 整數(shù)類型(byte/short/int/long)

整數(shù)類型直接以二進(jìn)制補(bǔ)碼形式存儲(補(bǔ)碼是計(jì)算機(jī)中表示有符號整數(shù)的標(biāo)準(zhǔn)方式,可統(tǒng)一加減法運(yùn)算):

  • byte(8位):如十進(jìn)制66存儲為 01000010(符號位0表示正數(shù),數(shù)值位為66的二進(jìn)制)。
  • int(32位):如十進(jìn)制1存儲為 00000000 00000000 00000000 00000001(32位補(bǔ)碼,高位補(bǔ)0)。
  • long(64位):在int的基礎(chǔ)上擴(kuò)展到64位,高位補(bǔ)0或符號位。

二、 浮點(diǎn)類型(float/double)

浮點(diǎn)類型遵循IEEE 754標(biāo)準(zhǔn),以二進(jìn)制形式存儲,但結(jié)構(gòu)更復(fù)雜(分為符號位、指數(shù)位、尾數(shù)位):

  • float(32位):1位符號位 + 8位指數(shù)位 + 23位尾數(shù)位。
  • double(64位):1位符號位 + 11位指數(shù)位 + 52位尾數(shù)位。
    例如,十進(jìn)制3.14f(float類型)會被轉(zhuǎn)換為對應(yīng)的32位二進(jìn)制浮點(diǎn)格式存儲。

三、 字符類型(char)

char類型存儲Unicode字符編碼(本質(zhì)是無符號整數(shù)),以16位二進(jìn)制形式存儲:

  • 例如字符'A'的Unicode編碼是65,對應(yīng)二進(jìn)制 00000000 01000001(16位)。
  • 中文字符'中'的Unicode編碼是20013,對應(yīng)二進(jìn)制 01001110 00101101

四、 布爾類型(boolean)

boolean類型比較特殊,Java規(guī)范未明確其占用的比特?cái)?shù)(不同JVM實(shí)現(xiàn)可能不同),但本質(zhì)仍是二進(jìn)制表示:

  • 通常用1位二進(jìn)制表示(0對應(yīng)false,1對應(yīng)true),但為了內(nèi)存對齊,實(shí)際可能占用1字節(jié)(8位),僅用最低位表示真假。

Java中的整數(shù)存儲

一、Java中整數(shù)的存儲:補(bǔ)碼是唯一標(biāo)準(zhǔn)

Java中所有有符號整數(shù)(byte/short/int/long統(tǒng)一使用補(bǔ)碼存儲,不存在原碼或反碼的直接使用,這是Java為簡化運(yùn)算和硬件適配做的設(shè)計(jì):

  • int類型(32位):最高位為符號位,范圍-2³¹ ~ 2³¹-1,其中-2³¹-2147483648)是特殊值,補(bǔ)碼為10000000 00000000 00000000 00000000(無對應(yīng)的原碼/反碼)。
  • long類型(64位):同理,范圍-2?³ ~ 2?³-1,補(bǔ)碼存儲。

示例
十進(jìn)制-5int補(bǔ)碼計(jì)算:
原碼(符號位1+數(shù)值位5)→ 10000000 00000000 00000000 00000101
反碼(符號位不變,數(shù)值位取反)→ 11111111 11111111 11111111 11111010
補(bǔ)碼(反碼+1)→ 11111111 11111111 11111111 11111011(Java中實(shí)際存儲的形式)

二、Java中的位運(yùn)算符:直接操作二進(jìn)制補(bǔ)碼

Java支持5種位運(yùn)算符(針對整數(shù)類型),操作的是數(shù)值的補(bǔ)碼二進(jìn)制位:

運(yùn)算符名稱規(guī)則(逐位操作)示例(int類型)
&按位與全1為1,否則為03 & 5 → 00000011 & 00000101 = 00000001 → 1
``按位或按位或
^按位異或不同為1,相同為03 ^ 5 → 00000011 ^ 00000101 = 00000110 → 6
~按位取反0變1,1變0(補(bǔ)碼取反)~3 → ~00000011 = 11111100(補(bǔ)碼)→ -4
<<左移左移n位,右補(bǔ)03 << 2 → 00000011 << 2 = 00001100 → 12
>>算術(shù)右移右移n位,左補(bǔ)符號位(正數(shù)補(bǔ)0,負(fù)數(shù)補(bǔ)1)-8 >> 1 → 11111000 >> 1 = 11111100 → -4
>>>無符號右移右移n位,左補(bǔ)0(忽略符號位)-1 >>> 1 → 11111111... >>> 1 = 01111111... → 2147483647

關(guān)鍵特性

  1. 類型提升:對byte/short進(jìn)行位運(yùn)算時(shí),會先自動提升為int(32位),結(jié)果也是int
    例:byte b = 3; byte c = (byte)(b << 1);(需強(qiáng)制轉(zhuǎn)型,否則結(jié)果為int)。
  2. 移位位數(shù)取模:移位位數(shù)若超過類型位數(shù)(如int移32位),會對位數(shù)取模(int移33位 = 移1位,33 % 32 = 1)。

三、掩碼在Java中的典型應(yīng)用

掩碼(mask)結(jié)合位運(yùn)算,在Java中常用于權(quán)限控制、數(shù)據(jù)解析、狀態(tài)標(biāo)記等場景:

1. 權(quán)限控制(用二進(jìn)制位表示不同權(quán)限)

// 定義權(quán)限掩碼(每個(gè)權(quán)限對應(yīng)1位)
public class Permission {
    public static final int READ = 1 << 0;   // 0001(1):讀權(quán)限
    public static final int WRITE = 1 << 1;  // 0010(2):寫權(quán)限
    public static final int EXEC = 1 << 2;   // 0100(4):執(zhí)行權(quán)限

    public static void main(String[] args) {
        int permissions = READ | WRITE;  // 組合權(quán)限:0011(3)

        // 檢查是否有寫權(quán)限(用&)
        boolean canWrite = (permissions & WRITE) != 0; // true

        // 添加執(zhí)行權(quán)限(用|)
        permissions |= EXEC;  // 0111(7)

        // 移除讀權(quán)限(用& ~)
        permissions &= ~READ; // 0110(6)
    }
}

2. 解析二進(jìn)制協(xié)議數(shù)據(jù)(提取特定字段)

假設(shè)某協(xié)議用16位二進(jìn)制表示“命令(高8位)+ 參數(shù)(低8位)”:

short data = 0x1234; // 二進(jìn)制:00010010 00110100(高8位0x12,低8位0x34)

// 提取高8位(命令):右移8位,并用0xFF掩碼保留低8位
int command = (data >> 8) & 0xFF; // 0x12(18)

// 提取低8位(參數(shù)):用0xFF掩碼保留低8位
int param = data & 0xFF; // 0x34(52)

四、注意事項(xiàng)

  1. 溢出問題:位運(yùn)算可能導(dǎo)致溢出(如int最大值左移1位變?yōu)樨?fù)數(shù)),但Java不拋異常,直接按補(bǔ)碼截?cái)唷?/li>
  2. boolean不支持位運(yùn)算boolean類型不能參與位運(yùn)算(需用&&/||邏輯運(yùn)算)。
  3. 浮點(diǎn)數(shù)無位運(yùn)算float/double不支持位運(yùn)算符(底層是IEEE 754浮點(diǎn)格式,需先轉(zhuǎn)整數(shù)再操作)。

二進(jìn)制運(yùn)算符應(yīng)用場景

Java中除了位移運(yùn)算符(<<、>>、>>>),還有另外4種核心二進(jìn)制運(yùn)算符:按位與(&、按位或(|、按位異或(^按位取反(~。它們直接對整數(shù)的補(bǔ)碼二進(jìn)制位進(jìn)行逐位操作,廣泛用于位級數(shù)據(jù)處理、權(quán)限控制、編碼解碼等場景。

一、按位與(&):全1為1,否則為0

規(guī)則:兩個(gè)操作數(shù)的對應(yīng)二進(jìn)制位進(jìn)行比較,只有當(dāng)兩個(gè)位都為1時(shí),結(jié)果位才為1;其他情況(0&0、0&1、1&0)結(jié)果位為0。

示例(以8位二進(jìn)制為例):

計(jì)算 3 & 5

  • 3的補(bǔ)碼:00000011
  • 5的補(bǔ)碼:00000101
  • 逐位與運(yùn)算:
  00000011
& 00000101
-----------
  00000001  // 結(jié)果為1(十進(jìn)制)

核心應(yīng)用場景:

  1. 提取/保留特定位(配合掩碼):
    用掩碼(mask)中為1的位“保留”目標(biāo)數(shù)的對應(yīng)位,為0的位“清除”對應(yīng)位。
    例:提取int類型的低8位(取最后一個(gè)字節(jié)):
int num = 0x123456; // 二進(jìn)制:00010010 00110100 01010110
int mask = 0xFF;    // 掩碼:00000000 00000000 11111111
int result = num & mask; // 0x56(僅保留低8位)
  1. 判斷奇偶性
    一個(gè)數(shù)的二進(jìn)制末位為1則是奇數(shù),為0則是偶數(shù)。通過與1按位與可快速判斷:
boolean isOdd = (num & 1) == 1; // 末位為1 → 奇數(shù)
  1. 清零操作
    與全0掩碼按位與,可將目標(biāo)數(shù)清零(num & 0 → 0)。

二、按位或(|):有1為1,全0為0

規(guī)則:兩個(gè)操作數(shù)的對應(yīng)二進(jìn)制位進(jìn)行比較,只要有一個(gè)位為1,結(jié)果位就為1;只有當(dāng)兩個(gè)位都為0時(shí),結(jié)果位才為0。

示例:

計(jì)算 3 | 5

  • 3的補(bǔ)碼:00000011
  • 5的補(bǔ)碼:00000101
  • 逐位或運(yùn)算:
  00000011
| 00000101
-----------
  00000111  // 結(jié)果為7(十進(jìn)制)

核心應(yīng)用場景:

  1. 設(shè)置特定位為1(配合掩碼):
    用掩碼中為1的位“強(qiáng)制設(shè)置”目標(biāo)數(shù)的對應(yīng)位為1,其他位保持不變。
    例:將int的第3位(從0開始)設(shè)為1:
int num = 0b1001; // 二進(jìn)制1001(9)
int mask = 1 << 3; // 掩碼1000(第3位為1)
int result = num | mask; // 1001 | 1000 = 1001(若原位為0則變?yōu)?)
  1. 組合權(quán)限/狀態(tài)
    用不同位表示不同權(quán)限(如READ=1<<0、WRITE=1<<1),通過|組合多個(gè)權(quán)限:
int permissions = READ | WRITE | EXEC; // 組合讀、寫、執(zhí)行權(quán)限
  1. 填充數(shù)據(jù)
    將低n位填充為1(如num | ((1 << n) - 1)),用于范圍限制。

三、按位異或(^):不同為1,相同為0

規(guī)則:兩個(gè)操作數(shù)的對應(yīng)二進(jìn)制位進(jìn)行比較,若兩個(gè)位不同(0和1),結(jié)果位為1;若相同(0和0或1和1),結(jié)果位為0。

示例:

計(jì)算 3 ^ 5

  • 3的補(bǔ)碼:00000011
  • 5的補(bǔ)碼:00000101
  • 逐位異或運(yùn)算:
  00000011
^ 00000101
-----------
  00000110  // 結(jié)果為6(十進(jìn)制)

核心應(yīng)用場景:

  1. 翻轉(zhuǎn)特定位
    用掩碼中為1的位“翻轉(zhuǎn)”目標(biāo)數(shù)的對應(yīng)位(0變1,1變0),為0的位保持不變。
    例:翻轉(zhuǎn)int的低4位:
int num = 0b1010; // 1010
int mask = 0b1111; // 掩碼1111
int result = num ^ mask; // 1010 ^ 1111 = 0101(低4位翻轉(zhuǎn))
  1. 不借助臨時(shí)變量交換兩個(gè)數(shù)
    利用異或的特性(a ^ a = 0,a ^ 0 = a)實(shí)現(xiàn)無臨時(shí)變量交換:
int a = 3, b = 5;
a = a ^ b; // a = 3^5 = 6
b = a ^ b; // b = 6^5 = 3(原a的值)
a = a ^ b; // a = 6^3 = 5(原b的值)
  1. 簡單加密/校驗(yàn)
    對數(shù)據(jù)與密鑰異或?qū)崿F(xiàn)加密,解密時(shí)再次異或相同密鑰:
int data = 0x1234;
int key = 0x5678;
int encrypted = data ^ key; // 加密
int decrypted = encrypted ^ key; // 解密(恢復(fù)原數(shù)據(jù))

四、按位取反(~):0變1,1變0

規(guī)則:對操作數(shù)的每一位二進(jìn)制位進(jìn)行“取反”(0→1,1→0),包括符號位。結(jié)果為“操作數(shù)的補(bǔ)碼取反”(對int是32位取反,long是64位取反)。

示例(32位int):

計(jì)算 ~3

  • 3的補(bǔ)碼:00000000 00000000 00000000 00000011
  • 按位取反:11111111 11111111 11111111 11111100(補(bǔ)碼)
  • 轉(zhuǎn)換為十進(jìn)制:-4(補(bǔ)碼取反后為負(fù)數(shù),計(jì)算方式見補(bǔ)碼規(guī)則)

核心應(yīng)用場景:

  1. 生成反掩碼
    對掩碼取反得到“反掩碼”,用于清除特定位(配合&運(yùn)算)。
    例:清除int的高16位:
int num = 0x12345678;
int mask = 0xFFFF0000; // 高16位為1的掩碼
int result = num & ~mask; // 清除高16位,保留低16位(0x5678)
  1. 計(jì)算負(fù)數(shù)的補(bǔ)碼
    取反加1是求負(fù)數(shù)補(bǔ)碼的方法(~n + 1 = -n),例:~3 + 1 = -3
  2. 位運(yùn)算中的“非”操作
    對布爾相關(guān)的位狀態(tài)取反(如flag = ~flag & 1,將0和1互轉(zhuǎn))。

五、左移(<<):高效的“乘以2?”運(yùn)算

左移的核心特性是:無溢出時(shí),a << n** 等價(jià)于 **a × 2?,且位操作比乘法指令執(zhí)行更快(硬件層面僅需移位,無需復(fù)雜計(jì)算)。因此,左移主要用于需要“快速放大數(shù)值”或“按2的冪次調(diào)整范圍”的場景。

1. 性能敏感的乘法計(jì)算

在高頻計(jì)算場景(如游戲引擎、實(shí)時(shí)數(shù)據(jù)處理)中,用左移替代× 2?可提升性能。
例:

  • 計(jì)算a × 8(即a × 2³):a << 3a * 8 執(zhí)行更快;
  • 圖形渲染中計(jì)算像素地址(如每行像素?cái)?shù)為width,第y行的起始地址可表示為 baseAddress + (y << log2(pixelSize)),通過左移快速計(jì)算偏移量)。

2. 生成掩碼或標(biāo)志位

左移可快速生成“僅某一位為1”的二進(jìn)制掩碼(用于位運(yùn)算中的權(quán)限控制、狀態(tài)標(biāo)記)。
例:

// 生成第n位為1的掩碼(如第3位:1000)
int mask = 1 << 3; // 二進(jìn)制1000,對應(yīng)十進(jìn)制8

這是權(quán)限控制、狀態(tài)位設(shè)計(jì)的基礎(chǔ)(如前面提到的READ = 1 << 0、WRITE = 1 << 1)。

3. 調(diào)整數(shù)值范圍(縮放)

在需要按2的冪次縮放數(shù)據(jù)時(shí)(如將小范圍數(shù)值映射到更大范圍),左移是簡潔的實(shí)現(xiàn)方式。
例:將8位灰度值(0~255)映射到32位ARGB顏色的紅色通道(需左移16位):

int gray = 0x80; // 8位灰度值(128)
int redChannel = gray << 16; // 映射到ARGB的紅色通道(0x800000)

六、算術(shù)右移(>>):有符號數(shù)的“除以2?”運(yùn)算

算術(shù)右移的核心特性是:a >> n** 等價(jià)于 a ÷ 2?(向下取整),且保持符號不變**(正數(shù)仍為正,負(fù)數(shù)仍為負(fù))。因此,它適合處理“有符號數(shù)的縮小”或“需要保留符號的位移”場景。

1. 有符號數(shù)的除法優(yōu)化

與左移對應(yīng),算術(shù)右移可替代÷ 2?,且比除法指令更快,尤其適合負(fù)數(shù)場景(保證結(jié)果仍為負(fù)數(shù))。
例:

  • 計(jì)算a ÷ 4(即a ÷ 2²):a >> 2a / 4 更高效;
  • 負(fù)數(shù)除法:-8 >> 1 結(jié)果為-4(正確),而若用無符號右移會得到正數(shù)(錯(cuò)誤)。

2. 二分查找中的中間索引計(jì)算

在二分查找等算法中,計(jì)算中間索引(mid = (left + right) / 2)時(shí),用算術(shù)右移可避免溢出并提升效率。
例:

int left = 0, right = 1000;
int mid = (left + right) >> 1; // 等價(jià)于 (left + right) / 2,結(jié)果為500

(注:更嚴(yán)謹(jǐn)?shù)膶懛ㄊ?code>left + ((right - left) >> 1),避免left + right溢出,但核心仍依賴右移的除法特性。)

3. 音頻/視頻的音量調(diào)整(按比例縮小)

在多媒體處理中,音量調(diào)整本質(zhì)是對音頻采樣值(有符號整數(shù))按比例縮小,算術(shù)右移可高效實(shí)現(xiàn)“除以2?”的衰減。
例:將音量衰減為原來的1/2(右移1位):

short sample = 32767; // 音頻采樣值(有符號16位)
short attenuated = (short) (sample >> 1); // 16383(約為32767/2)

七、無符號右移(>>>):無符號數(shù)據(jù)處理與位提取

無符號右移的核心特性是:左側(cè)補(bǔ)0,不考慮符號位,將數(shù)值視為“無符號整數(shù)”處理。因此,它適合處理“無符號數(shù)據(jù)”或“需要提取二進(jìn)制位”的場景(忽略符號影響)。

1. 解析二進(jìn)制協(xié)議/文件格式

網(wǎng)絡(luò)協(xié)議(如TCP/UDP報(bào)文頭)、文件格式(如圖片、視頻)的字段常以“無符號二進(jìn)制位”存儲(如長度、標(biāo)志),無符號右移可正確提取這些字段。
例:解析一個(gè)32位無符號整數(shù)的高16位和低16位:

int unsignedInt = 0x12345678; // 32位無符號數(shù)(十六進(jìn)制)
int high16 = unsignedInt >>> 16; // 提取高16位:0x1234
int low16 = unsignedInt & 0xFFFF; // 提取低16位:0x5678

2. 處理哈希值或UUID(無符號場景)

哈希值(如Object.hashCode())、UUID等通常被視為無符號數(shù),無符號右移可避免符號位干擾,正確處理這些值的位操作。
例:將32位哈希值轉(zhuǎn)換為0~1的浮點(diǎn)數(shù)(需視為無符號數(shù)):

int hashCode = "test".hashCode();
float ratio = (hashCode >>> 1) / (float) (1 << 31); // 無符號右移后計(jì)算比例

3. 生成非負(fù)整數(shù)(消除符號位影響)

當(dāng)需要將負(fù)數(shù)轉(zhuǎn)換為非負(fù)數(shù)(僅關(guān)注其補(bǔ)碼的二進(jìn)制位模式)時(shí),無符號右移可直接“抹除”符號位(左側(cè)補(bǔ)0)。
例:將-1(32位全1)轉(zhuǎn)換為最大非負(fù)整數(shù):

int negative = -1;
int positive = negative >>> 0; // 結(jié)果為2147483647(32位無符號最大值)

4. 位逆序或循環(huán)移位(底層算法)

在密碼學(xué)、編碼算法中,需要對二進(jìn)制位進(jìn)行逆序或循環(huán)移位,無符號右移可配合其他位運(yùn)算實(shí)現(xiàn)(避免符號位干擾)。
例:將8位二進(jìn)制位逆序(如1011001001001101):

byte b = (byte) 0xB2; // 二進(jìn)制10110010
int reversed = 0;
for (int i = 0; i < 8; i++) {
    reversed = (reversed << 1) | ((b >>> i) & 1); // 無符號右移提取每一位
}
// reversed結(jié)果為0x4D(二進(jìn)制01001101)

總結(jié)

三種位移運(yùn)算符的應(yīng)用場景可歸納為:

運(yùn)算符核心特性典型場景
&全1為1,否則為0提取特定位、判斷奇偶、清零
``有1為1,全0為0
^不同為1,相同為0翻轉(zhuǎn)特定位、交換變量、簡單加密
~0變1,1變0生成反掩碼、計(jì)算補(bǔ)碼、位狀態(tài)取反
<<等價(jià)于× 2?,快速放大性能敏感的乘法、生成掩碼、數(shù)值范圍調(diào)整
>>等價(jià)于÷ 2?,保持符號有符號數(shù)除法、二分查找、音量調(diào)整
>>>無符號處理,左側(cè)補(bǔ)0二進(jìn)制協(xié)議解析、哈希值處理、位提取

理解這些場景的關(guān)鍵是:根據(jù)是否需要“保留符號”“處理無符號數(shù)據(jù)”或“追求運(yùn)算效率”選擇合適的位移方式,充分利用位操作的高性能特性。

補(bǔ)充:反碼循環(huán)進(jìn)位

在反碼的加法運(yùn)算中,“循環(huán)進(jìn)位”是一個(gè)特殊的處理規(guī)則,指的是當(dāng)兩個(gè)反碼相加時(shí),若最高位(符號位)產(chǎn)生進(jìn)位,則需要將這個(gè)進(jìn)位“循環(huán)”到結(jié)果的最低位(即把進(jìn)位值1加到結(jié)果的最低位),以保證運(yùn)算結(jié)果的正確性。

為什么會出現(xiàn)循環(huán)進(jìn)位?

反碼的核心問題是0的表示不唯一(存在+0和-0),這導(dǎo)致反碼的加法運(yùn)算可能產(chǎn)生“虛假進(jìn)位”。如果直接丟棄最高位的進(jìn)位,會導(dǎo)致結(jié)果錯(cuò)誤,因此需要通過“循環(huán)進(jìn)位”修正。

舉例說明循環(huán)進(jìn)位的過程

以8位反碼為例,計(jì)算 3 + (-1)

  1. 先寫出兩數(shù)的反碼:
    • 3的反碼:00000011(正數(shù)反碼=原碼)
    • -1的原碼:10000001 → 反碼(符號位不變,數(shù)值位取反):11111110
  2. 反碼相加:
  00000011  (3的反碼)
+ 11111110  (-1的反碼)
-----------
100000001  (結(jié)果,最高位產(chǎn)生進(jìn)位1)
  1. 處理循環(huán)進(jìn)位:
    最高位的進(jìn)位“1”不能丟棄,需加到結(jié)果的最低位:
  00000001  (去掉最高位進(jìn)位后的結(jié)果)
+       1  (循環(huán)進(jìn)位的1)
-----------
  00000010  (最終結(jié)果,對應(yīng)十進(jìn)制2,正確)

若不循環(huán)進(jìn)位會怎樣?

如果直接丟棄最高位的進(jìn)位,上面的結(jié)果會是 00000001(對應(yīng)十進(jìn)制1),與正確結(jié)果2不符??梢?,循環(huán)進(jìn)位是反碼加法中修正錯(cuò)誤的必要步驟。

總結(jié)

  • 循環(huán)進(jìn)位:反碼加法中,最高位產(chǎn)生的進(jìn)位需加到結(jié)果的最低位,是反碼為解決“0的雙重表示”導(dǎo)致的運(yùn)算錯(cuò)誤而設(shè)計(jì)的規(guī)則。
  • 局限性:這種處理增加了硬件實(shí)現(xiàn)的復(fù)雜度,這也是反碼僅作為“過渡形式”存在,而計(jì)算機(jī)最終采用補(bǔ)碼(無需循環(huán)進(jìn)位)的重要原因。

到此這篇關(guān)于Java二進(jìn)制運(yùn)算符超詳細(xì)講解及擴(kuò)展知識的文章就介紹到這了,更多相關(guān)Java二進(jìn)制運(yùn)算符內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java中File類應(yīng)用遍歷文件夾下所有文件

    java中File類應(yīng)用遍歷文件夾下所有文件

    這篇文章主要為大家詳細(xì)介紹了java中File類應(yīng)用遍歷文件夾下所有文件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • 淺談JDK7和JDK8的區(qū)別在哪

    淺談JDK7和JDK8的區(qū)別在哪

    面試總是遇到這個(gè)問題,做一個(gè)小總結(jié),文中有非常詳細(xì)的介紹,對正在學(xué)習(xí)java的小伙伴們很有幫助,需要的朋友可以參考下
    2021-06-06
  • Java?list如何實(shí)現(xiàn)將指定元素排在第一位

    Java?list如何實(shí)現(xiàn)將指定元素排在第一位

    這篇文章主要為大家詳細(xì)介紹了Java?list中如何實(shí)現(xiàn)將指定元素排在第一位,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-02-02
  • MyBatisPlus?TypeHandler自定義字段類型轉(zhuǎn)換Handler

    MyBatisPlus?TypeHandler自定義字段類型轉(zhuǎn)換Handler

    這篇文章主要為大家介紹了MyBatisPlus?TypeHandler自定義字段類型轉(zhuǎn)換Handler示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • 批量將現(xiàn)有Jar包上傳到Maven私服

    批量將現(xiàn)有Jar包上傳到Maven私服

    今天小編就為大家分享一篇關(guān)于批量將現(xiàn)有Jar包上傳到Maven私服,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • java中的i++和++i的區(qū)別詳解

    java中的i++和++i的區(qū)別詳解

    這篇文章主要介紹了java中的i++和++i的區(qū)別詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • win10安裝JDK14.0.2的詳細(xì)安裝過程

    win10安裝JDK14.0.2的詳細(xì)安裝過程

    這篇文章主要介紹了win10安裝JDK14.0.2的詳細(xì)安裝過程的相關(guān)資料,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • 解決IDEA開發(fā)工具右側(cè)沒有Maven工具欄的問題

    解決IDEA開發(fā)工具右側(cè)沒有Maven工具欄的問題

    這篇文章主要給大家解決了IDEA開發(fā)工具右側(cè)沒有Maven工具欄的問題,文中有詳細(xì)的解決步驟,如果有遇到一樣問題的小伙伴,可以參考閱讀本文
    2023-09-09
  • Spring Boot 中的 @ConditionalOnBean 注解場景分析

    Spring Boot 中的 @ConditionalOnBean 注解場景分析

    本文詳細(xì)介紹了Spring Boot中的@ConditionalOnBean注解的使用場景、原理和基本用法,通過多個(gè)示例,展示了如何使用該注解根據(jù)Bean是否存在來動態(tài)地注冊或跳過特定的Bean,感興趣的朋友一起看看吧
    2025-03-03
  • Java基于高精度整型實(shí)現(xiàn)fibonacci數(shù)列的方法

    Java基于高精度整型實(shí)現(xiàn)fibonacci數(shù)列的方法

    這篇文章主要介紹了Java基于高精度整型實(shí)現(xiàn)fibonacci數(shù)列的方法,是比較典型的算法,需要的朋友可以參考下
    2014-09-09

最新評論