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

詳解Java的位運(yùn)算

 更新時(shí)間:2023年04月11日 10:20:33   作者:CrazyDragon_King  
這篇文章主要介紹了詳解Java的位運(yùn)算,程序中的所有數(shù)在計(jì)算機(jī)內(nèi)存中都是以二進(jìn)制的形式儲(chǔ)存的。位運(yùn)算就是直接對整數(shù)在內(nèi)存中的二進(jìn)制位進(jìn)行操作,需要的朋友可以參考下

位運(yùn)算

很久以前學(xué)習(xí)過位運(yùn)算,但是很久不用,感覺都忘得差不多了。最近看了幾處位運(yùn)算的代碼,發(fā)現(xiàn)都看不懂了,哈。也是時(shí)候回來補(bǔ)一補(bǔ)基礎(chǔ)知識(shí)了。

程序中的所有數(shù)在計(jì)算機(jī)內(nèi)存中都是以二進(jìn)制的形式儲(chǔ)存的。位運(yùn)算就是直接對整數(shù)在內(nèi)存中的二進(jìn)制位進(jìn)行操作。

位運(yùn)算的運(yùn)算符:

運(yùn)算符含義
&按位與
|按位或
~按位取反
^按位異或
<<左移
>>帶符號(hào)右移
>>>無符號(hào)右移

這些算是很基礎(chǔ)的知識(shí)了,但是太久不用,還是難免會(huì)遺忘了,在編碼的同時(shí),可以多多使用!

Talk is cheap, show me the code.

說明:單獨(dú)討論這些確實(shí)是很難看到應(yīng)用的地方,如果有不太清楚的可以去看看其他人的總結(jié)。

我們以一個(gè)代碼來看看位運(yùn)算的應(yīng)用:

public final void writeInt(int v) throws IOException {
	  out.write((v >>> 24) & 0xFF);
	  out.write((v >>> 16) & 0xFF);
	  out.write((v >>>  8) & 0xFF);
	  out.write((v >>>  0) & 0xFF);
	  incCount(4);
}

這段代碼是 DataOutputStream 類中的一個(gè)方法,用于將一個(gè) int 型的整數(shù)寫入流中。這個(gè)方法的命名是很有意思的,它和 OutputStream 中的 public abstract void write(int b) throws IOException 這個(gè)方法是完全不同的。這個(gè)方法的參數(shù)似乎是表示它可以將一個(gè) int 型整數(shù)寫入流中,但是方法的功能不是靠猜測的,而是要看方法的描述。

public abstract void write(int b) throws IOException

API 中的介紹:

Writes the specified byte to this output stream. The general contract for write is that one byte is written to the output stream. The byte to be written is the eight low-order bits of the argument b. The 24 high-order bits of b are ignored.

它是將一個(gè)特定的字節(jié)寫入流中,我們知道一個(gè)int型變量占32位,一個(gè)byte占8位,所以一個(gè)小于256(2^8)的int型整數(shù)和byte型整數(shù)的最后8位是相同的。

因此這個(gè)方法是寫入一個(gè)int型變量的最低8位,而將剩下的24位忽略。使用這個(gè)方法的時(shí)候,要格外注意!

The byte to be written is the eight low-order bits of the argument b. The 24 high-order bits of b are ignored.

所以,將一個(gè)int型的變量完整的寫入流中,并不是一個(gè)很簡單的問題。讓我們再回到上面這端代碼: 它是連續(xù)四次寫入,每次寫入一個(gè)字節(jié)的數(shù)據(jù),這樣一個(gè)int型的變量,就被變?yōu)?個(gè)字節(jié)寫入流中了。

out.write((v >>> 24) & 0xFF); 這個(gè)方法就是上面的寫入較低的8位數(shù)字,這個(gè)具體實(shí)現(xiàn)是相應(yīng)的子類提供的。

我們來看看圖解: 一個(gè)簡單的與運(yùn)算:可以看出運(yùn)算的結(jié)果是保留了低8位,這個(gè)就是 (v>>>24) & 0xFF 運(yùn)算的結(jié)果。

在這里插入圖片描述

那么如何獲取高8位的值呢?這就要使用移位運(yùn)算進(jìn)行操作了:

在這里插入圖片描述

通過進(jìn)行移位操作,就可以獲取每8位的數(shù)據(jù),然后再進(jìn)行按位與 & 運(yùn)算,就可以將一個(gè)int型整數(shù)完全的寫入流中了。

代碼演示

代碼

package dragon;

/**
 * 分析這一個(gè)方法,目前水平有限,先從最簡單的做起!
 * */

//		   public final void writeInt(int v) throws IOException {
//        out.write((v >>> 24) & 0xFF);
//        out.write((v >>> 16) & 0xFF);
//        out.write((v >>>  8) & 0xFF);
//        out.write((v >>>  0) & 0xFF);
//        incCount(4);
//    }


//上面這段代碼是將一個(gè)32位整型,寫入輸出流。
//并且是將32位整型分為4個(gè)部分,每次寫入8位。
//這是Java的特性。


public class DataOutputStreamAnalysis {
	public static void main(String[] args) {
		DataOutputStreamAnalysis analysis = new DataOutputStreamAnalysis();
		analysis.analysis(65535);
	}
	
	public void analysis(int number) {
		int number1, number2, number3, number4;  //后面的數(shù)字表示是一個(gè)32位整型的第幾個(gè)8位。
		number1 = (number >>> 24) & 0xFF;    
		number2 = (number >>> 16) & 0xFF;    
		number3 = (number >>> 8) & 0xFF;
		number4 = (number >>> 0) & 0xFF;
		
		
		
		System.out.println(this.format(Integer.toBinaryString(number))+"  原始數(shù)據(jù)"); 
		System.out.println(this.format(Integer.toBinaryString(number1))+"  原始數(shù)據(jù)第一個(gè)8位");
		System.out.println(this.format(Integer.toBinaryString(number2))+"  原始數(shù)據(jù)第二個(gè)8位");
		System.out.println(this.format(Integer.toBinaryString(number3))+"  原始數(shù)據(jù)第三個(gè)8位");
		System.out.println(this.format(Integer.toBinaryString(number4))+"  原始數(shù)據(jù)第四個(gè)8位");
	}
	
	/**
	 * 輸入一個(gè)二進(jìn)制字符串,將其格式化,因?yàn)檎褪?
	 * 占32位的,但是轉(zhuǎn)換成的二進(jìn)制字符串,并沒有32位*/
	public String format(String bstr) {
		int len = bstr.length();
		StringBuilder sb = new StringBuilder(35);
		for (int i = 0; i < 32-len; i++) {
			sb.append("0");
		}
		sb.append(bstr);
		sb.insert(8, " ");
		sb.insert(17, " ");
		sb.insert(26, " ");   //前面插入一個(gè)字符后,所有字符的索引都變了!
		return sb.toString();
	}
}

結(jié)果

在這里插入圖片描述

說明: 這里沒有考慮負(fù)數(shù)的情況,不過都是一樣的,只是負(fù)數(shù)的表示相對麻煩一點(diǎn)而已。只要理解正數(shù),負(fù)數(shù)也不是什么問題了。

位運(yùn)算的應(yīng)用

1.判斷 int 型變量x是奇書還是偶數(shù)

將變量 x 和 1 進(jìn)行按位與運(yùn)算,如果結(jié)果為 0,則變量x為偶數(shù),否則為奇數(shù)。

if (x & 1 ==0) 
	System.out.println("x是偶數(shù)");
if (x & 1 == 1) 
    System.out.println("x是奇數(shù)");

說明:這個(gè)還是很好理解的,因?yàn)榕紨?shù)的最后移位一定是 0。(二進(jìn)制表示)

2.取 int 型變量 x 的第 k 位 將變量 x 右移 k 位,再和1進(jìn)行邏輯與運(yùn)算,結(jié)果即為變量 x 第 k 位的二進(jìn)制值。

表達(dá)式:x >> k & 1 (推薦加上括號(hào),這樣顯得更加清晰明了。)

3.將 int 型變量 x 的第 k 位置 1 將 1 左移 k 位,再和變量 x 進(jìn)行邏輯或運(yùn)算,則將變量 x 的第 k 位置 1,其它位保持不變。

表達(dá)式:x = x | (1 << k)

4.將 int 型變量的第 k 位 清 0 將 1 左移 k 位再取反,將其結(jié)果再和變量 下進(jìn)行邏輯運(yùn)算,則將變量 x 的第 k 位清 0,其它位保持不變。

表達(dá)式位:x = x & ~(1 << k)

5.計(jì)算兩個(gè)整數(shù)的平均值

表達(dá)式位:(x & y) + ((x ^ y) >> 1)

6.對于大于1 的整數(shù) x,判斷 x 是不是 2 的冪

if (x & (x-1) == 0)
	System.out.println("x是2的次冪");

7.將一個(gè)數(shù)乘以 2 的 n 次冪

表達(dá)式:x = x << n

例如:將 x 擴(kuò)大 2 倍:x = x << 1

推薦使用位運(yùn)算的原因:

位運(yùn)算的速度是快于算術(shù)運(yùn)算的,因?yàn)槲贿\(yùn)算需要的指令少,執(zhí)行所需要的時(shí)間就少,會(huì)顯得很快,但是只有在大量執(zhí)行的情況下才能看出來位運(yùn)算的優(yōu)點(diǎn)。畢竟現(xiàn)在的計(jì)算機(jī)已經(jīng)越來越快了。

到此這篇關(guān)于詳解Java的位運(yùn)算的文章就介紹到這了,更多相關(guān)Java位運(yùn)算內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring Boot基礎(chǔ)學(xué)習(xí)之Mybatis操作中使用Redis做緩存詳解

    Spring Boot基礎(chǔ)學(xué)習(xí)之Mybatis操作中使用Redis做緩存詳解

    這篇文章主要給大家介紹了關(guān)于Spring Boot基礎(chǔ)學(xué)習(xí)之Mybatis操作中使用Redis做緩存的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用spring boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧
    2018-11-11
  • SpringBoot框架打包體積簡化過程圖解

    SpringBoot框架打包體積簡化過程圖解

    這篇文章主要介紹了SpringBoot框架打包體積簡化過程圖解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05
  • logback使用filter過濾日志操作

    logback使用filter過濾日志操作

    這篇文章主要介紹了logback使用filter過濾日志操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • Java設(shè)計(jì)者模式簡單工廠模式解析

    Java設(shè)計(jì)者模式簡單工廠模式解析

    這篇文章主要介紹了Java設(shè)計(jì)者模式簡單工廠模式解析,介紹了其簡介,實(shí)例以及優(yōu)缺點(diǎn)分析,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • Java貪心算法超詳細(xì)講解

    Java貪心算法超詳細(xì)講解

    人之初性本善,但是隨著自身的經(jīng)歷、生活環(huán)境等因素的影響,人逐漸會(huì)生出貪嗔癡。實(shí)際上不光人有貪念,我們的算法也會(huì)有貪念,今天就和大家介紹下一個(gè)有貪念的算法模型---貪心算法,看看一個(gè)算法是怎么產(chǎn)生貪念的
    2022-05-05
  • idea springboot 修改css,jsp不重啟實(shí)現(xiàn)頁面更新的問題

    idea springboot 修改css,jsp不重啟實(shí)現(xiàn)頁面更新的問題

    這篇文章主要介紹了idea springboot 修改css,jsp不重啟實(shí)現(xiàn)頁面更新的問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • Java實(shí)現(xiàn)JDK動(dòng)態(tài)代理的原理詳解

    Java實(shí)現(xiàn)JDK動(dòng)態(tài)代理的原理詳解

    這篇文章主要介紹了Java實(shí)現(xiàn)JDK動(dòng)態(tài)代理的原理詳解,Java常用的動(dòng)態(tài)代理模式有JDK動(dòng)態(tài)代理,也有cglib動(dòng)態(tài)代理,本文重點(diǎn)講解JDK的動(dòng)態(tài)代理,需要的小伙伴可以參考一下的相關(guān)資料
    2022-07-07
  • 計(jì)算Java數(shù)組長度函數(shù)的方法以及代碼分析

    計(jì)算Java數(shù)組長度函數(shù)的方法以及代碼分析

    在本篇內(nèi)容里,小編給大家整理了關(guān)于計(jì)算Java數(shù)組長度函數(shù)的方法以及代碼分析內(nèi)容,有興趣的朋友么可以學(xué)習(xí)參考下。
    2022-11-11
  • Spring、SpringMVC和SpringBoot的區(qū)別及說明

    Spring、SpringMVC和SpringBoot的區(qū)別及說明

    這篇文章主要介紹了Spring、SpringMVC和SpringBoot的區(qū)別及說明,具有很好的參考價(jià)值,希望對大家有所幫助。
    2022-10-10
  • 解決RedisTemplate的key默認(rèn)序列化器的問題

    解決RedisTemplate的key默認(rèn)序列化器的問題

    這篇文章主要介紹了解決RedisTemplate的key默認(rèn)序列化器的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03

最新評(píng)論