Java中的二進位及基本的位運算

来源:http://www.cnblogs.com/hysum/archive/2017/07/16/7190388.html
-Advertisement-
Play Games

Java中的二進位及基本的位運算 二進位是計算技術中廣泛採用的一種數制。二進位數據是用0和1兩個數位來表示的數。它的基數為2,進位規則是“逢二進一”,借位規則是“借一當二”,由18世紀德國數理哲學大師萊布尼茲發現。當前的電腦系統使用的基本上是二進位系統,數據在電腦中主要是以補碼的形式存儲的。計算 ...


Java中的二進位及基本的位運算



  二進位是計算技術中廣泛採用的一種數制二進位數據是用0和1兩個數位來表示的數。它的基數為2,進位規則是“逢二進一”,借位規則是“借一當二”,由18世紀德國數理哲學大師萊布尼茲發現。當前的電腦系統使用的基本上是二進位系統,數據在電腦中主要是以補碼的形式存儲的。電腦中的二進位則是一個非常微小的開關,用“開”來表示1,“關”來表示0。

  那麼Java中的二進位又是怎麼樣的呢?讓我們一起來揭開它神秘的面紗吧。


一、Java內置的進位轉換

有關十進位轉為二進位,和二進位轉為十進位這種基本的運算方法這裡就不展開講了。

在Java中內置了幾個方法來幫助我們進行各種進位的轉換。如下圖所示(以Integer整形為例,其他類型雷同):

1,十進位轉化為其他進位:

1 二進位:Integer.toHexString(int i);
2 八進位:Integer.toOctalString(int i);
3 十六進位:Integer.toBinaryString(int i);

2,其他進位轉化為十進位:

1 二進位:Integer.valueOf("0101",2).toString;
2 八進位:Integer.valueOf("376",8).toString;
3 十六進位:Integer.valueOf("FFFF",16).toString;

3,使用Integer類中的parseInt()方法和valueOf()方法都可以將其他進位轉化為10進位。

不同的是parseInt()方法的返回值是int類型,而valueOf()返回值是Integer對象。


二、基本的位運算

二進位可以和十進位一樣加減乘除,但是它還有更簡便的運算方式就是——位運算。比如在電腦中int類型的大小是32bit,可以用32位的二進位數來表示,所以我們可以用位運算來對int類型的數值進行計算,當然你也可以用平常的方法來計算一些數據,這裡我主要為大家介紹位運算的方法。我們會發現位運算有著普通運算方法不可比擬的力量。更多位運算應用請轉移到我下篇博文《神奇的位運算》

首先,看一下位運算的基本操作符:

優點:

  • 特定情況下,計算方便,速度快,被支持面廣
  • 如果用算數方法,速度慢,邏輯複雜
  • 位運算不限於一種語言,它是電腦的基本運算方法

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

(一)按位與&

兩位全為1,結果才為1

0&0=0;0&1=0;1&0=0;1&1=1

例如:51&5 即0011 0011 & 0000 0101 =0000 0001 因此51&5=1.

特殊用法

(1)清零。如果想將一個單元清零,即使其全部二進位位為0,只要與一個各位都是零的數值相與,結果為零。

(2)取一個數中指定位。

例如:設X=10101110,取X的低四位,用X&0000 1111=0000 1110即可得到。

方法:找一個數,對應x要取的位,該數的對應位為1,其餘位為零,此數與x進行“與運算”可以得到x中的指定位。

(二)按位或 |

只要有一個為1,結果就為1。

0|0=0; 0|1=1;1|0=1;1|1=1;

例如:51|5 即0011 0011 | 0000 0101 =0011 0111 因此51|5=55

 特殊用法

常用來對一個數據的某些位置1。

方法:找到一個數,對應x要置1的位,該數的對應位為1,其餘位為零。此數與x相或可使x中的某些位置1。

(三)異或 ^

兩個相應位為“異”(值不同),則該位結果為1,否則為0

0^0=0; 0^1=1; 1^0=1; 1^1=0;

例如:51^5 即0011 0011 ^ 0000 0101 =0011 0110 因此51^5=54

特殊用法

(1)  與1相異或,使特定位翻轉

方法:找一個數,對應X要翻轉的位,該數的對應為1,其餘位為零,此數與X對應位異或即可。

例如:X=1010 1110,使X低四位翻轉,用X^0000 1111=1010 0001即可得到。

(2)  與0相異或,保留原值

例如:X^0000 0000 =1010 1110

(3)兩個變數交換值

1.藉助第三個變數來實現

C=A;A=B;B=C;

2.利用加減法實現兩個變數的交換

 A=A+B;B=A-B;A=A-B;

3.用位異或運算來實現,也是效率最高的

原理:一個數異或本身等於0 ;異或運算符合交換律

A=A^B;B=A^B;A=A^B

(四)取反與運算~

對一個二進位數按位取反,即將0變為1,1變0

~1=0 ;~0=1

(五)左移<<

將一個運算對象的各二進位位全部左移若幹位(左邊的二進位位丟棄,右邊補0)

例如: 2<<1 =4    10<<1=100

若左移時捨棄的高位不包含1,則每左移一位,相當於該數乘以2。

例如:

       11(1011)<<2= 0010 1100=22

       11(00000000 00000000 00000000 1011)整形32bit

(六)右移>>

將一個數的各二進位位全部右移若幹位,正數左補0,負數左補1,右邊丟棄。若右移時舍高位不是1(即不是負數),操作數每右移一位,相當於該數除以2。

左補0還是補1得看被移數是正還是負。

例如:4>>2=4/2/2=1

        -14(即1111 0010)>>2 =1111 1100=-4

(七)無符號右移運算>>>

各個位向右移指定的位數,右移後左邊空出的位用零來填充,移除右邊的位被丟棄。

例如:-14>>>2

(即11111111 11111111 11111111 11110010)>>>2

=(00111111 11111111 11111111 11111100)=1073741820

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

上述提到的負數,他的二進位位表示和正數略有不同,所以在位運算的時候也與正數不同。

負數以其正數的補碼形式表示

以上述的-14為例,來簡單闡述一下原碼、反碼和補碼。

原 碼

一個整數按照絕對值大小轉化成的二進位數稱為原碼

例如:00000000 00000000 00000000 00001110 是14的原碼。

反 碼

將二進位數按位取反,所得到的新二進位數稱為原二進位數的反碼。

例如:將00000000 00000000 00000000 00001110 每一位取反,

得11111111 11111111 11111111 11110001

註意:這兩者互為反碼

補 碼

反碼加1稱為補碼

11111111 11111111 11111111 11110001 +1=

11111111 11111111 11111111 11110010

現在我們得到-14的二進位表示,現在將它左移

-14(11111111 11111111 11111111 11110010)<<2 =

11111111 11111111 11111111 11001000

=?

分析:這個二進位的首位為1,說明是補碼形式,現在我們要將補碼轉換為原碼(它的正值)

跟原碼轉換為補碼相反,將補碼轉換為原碼的步驟:

  1. 補碼減1得到反碼:(11000111)前24位為1,此處省略
  2. 反碼取反得到原碼(即該負數的正值)(00111000)
  3. 計算正值,正值為56
  4. 取正值的相反數,得到結果-56

結論:-14<<2 = -56


三、Java中進位運算

Java中二進位用的多嗎?

平時開發中“進位轉換”和“位操作”用的不多,Java處理的是高層。

在跨平臺中用的較多,如:文件讀寫,數據通信。

來看一個場景:

如果客戶機和伺服器都是用Java語言寫的程式,那麼當客戶機發送對象數據,我們就可以把要發送的數據序列化serializable,伺服器端得到序列化的數據之後就可以反序列化,讀出裡面的對象數據。

隨著客戶機訪問量的增大,我們不考慮伺服器的性能,其實一個可行的方案就是把伺服器的Java語言改成C語言。

C語言作為底層語言,反映速度都比Java語言要快,而此時如果客戶端傳遞的還是序列化的數據,那麼伺服器端的C語言將無法解析,怎麼辦呢?我們可以把數據轉為二進位(0,1),這樣的話伺服器就可以解析這些語言。

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

Java中基本數據類型有以下四種:

  1. Int數據類型:byte(8bit,-128~127)、short(16bit)、int(32bit)、long(64bit)
  2. float數據類型:單精度(float,32bit ) 、雙精度(double,64bit)
  3. boolean類型變數的取值有true、false(都是1bit)
  4. char數據類型:unicode字元,16bit

對應的類類型:

Integer、Float、Boolean、Character、Double、Short、Byte、Long

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

(一)數據類型轉為位元組

例如:int型8143(00000000 00000000 00011111 11001111)

=>byte[] b=[-49,31,0,0]

第一個(低端)位元組:8143>>0*8 & 0xff=(11001111)=207(或有符號-49)

第二個(低端)位元組:8143>>1*8 &0xff=(00011111)=31

第三個(低端)位元組:8143>>2*8 &0xff=00000000=0

第四個(低端)位元組:8143>>3*8 &0xff=00000000=0

 

我們註意到上面的(低端)是從右往左開始的,那什麼是低端呢?我們從大小端的角度來說明。

小端法(Little-Endian)

位位元組排放在記憶體的地址端即該值的起始地址,位位元組排位在記憶體的地址端

大端法(Big-Endian)

位位元組排放在記憶體的地址端即該值的起始地址,位位元組排位在記憶體的地址端

 

為什麼會有大小端模式之分呢?

這是因為在電腦系統中,我們是以位元組為單位的,每個地址單元都對應著一個位元組,一個位元組為8bit。但是在C語言中除了8bit的char之外,還有16bit的short型,32bit的long型(要看具體的編譯器),另外,對於位數大於8位的處理器,例如16位或者32位的處理器,由於寄存器寬度大於一個位元組,那麼必然存在著一個如果將多個位元組安排的問題。因此就導致了大端存儲模式和小端存儲模式。例如一個16bit的short型x,在記憶體中的地址為0x0010,x的值為0x1122,那麼0x11為高位元組,0x22為低位元組。對於大端模式,就將0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。小端模式,剛好相反。我們常用的X86結構是小端模式,而KEIL C51則為大端模式。很多的ARM,DSP都為小端模式。有些ARM處理器還可以由硬體來選擇是大端模式還是小端模式。

例如:32bit的數0x12 34 56 78(十二進位)

在Big-Endian模式CPU的存放方式(假設從地址0x4000開始存放)為

記憶體地址

0x4000

0x4001

0x4002

0x4003

存放內容

0x78

0x56

0x34

0x12

在Little-Endian模式CPU的存放方式(假設從地址0x4000開始存放)為

記憶體地址

0x4000

0x4001

0x4002

0x4003

存放內容

0x12

0x34

0x56

0x78

 (二)字元串轉化為位元組

1.字元串->位元組數組

1 String s;
2 byte[] bs=s.getBytes();

2.位元組數組->字元串

1 Byte[] bs=new byte[int];
2 String s =new String(bs);或
3 String s=new String(bs,encode);//encode指編碼方式,如utf-8

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

兩種類型轉化為位元組的方法都介紹了,下麵寫個小例子檢驗一下:

 1 public class BtyeTest {
 2     /*
 3      * int整型轉為byte位元組
 4      */
 5     public static byte[] intTOBtyes(int in){
 6         byte[] arr=new byte[4];
 7         for(int i=0;i<4;i++){
 8             arr[i]=(byte)((in>>8*i) & 0xff);
 9         }
10         return arr;
11     }
12     /*
13      * byte位元組轉為int整型
14      */
15     public static int bytesToInt(byte[] arr){
16         int sum=0;
17         for(int i=0;i<arr.length;i++){
18             sum+=(int)(arr[i]&0xff)<<8*i;
19         }
20         return sum;
21     }
22     public static void main(String[] args) {
23         // TODO Auto-generated method stub
24         byte[] arr=intTOBtyes(8143);
25         for(byte b:arr){
26             System.out.print(b+" ");
27         }
28         System.out.println();
29         System.out.println(bytesToInt(arr));
30         
31         //字元串與位元組數組
32         String str="雲開的立夏de博客園";
33         byte[] barr=str.getBytes();
34         
35         String str2=new String(barr);
36         System.out.println("字元串轉為位元組數組:");
37         for(byte b:barr){
38             System.out.print(b+" ");
39 
40         }
41         System.out.println();
42 
43         System.out.println("位元組數組換位字元串:"+str2);
44         
45          
46     }
47 
48 }

運行結果:


結束語:最近偷懶了,沒有好好學習,好幾天沒寫文了,哎,還請大家多多監督!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Windows Server 2012+ASP.NET +Mysql 最近用戶量突破10+以上,最大併發1300+ 資料庫CPU居高不下,一時達到100%臨界點,導致很多SQL命令執行發生錯誤,連接拒絕。 ...
  • 在上一篇我們在菜單欄創建了一個菜單,菜單上顯示了一個圖標跟文本。那麼我們自己創建的菜單如何修改自定義的菜單圖標呢。下麵娓娓道來。。。。。 首先你要有一個圖,創建一個32位的點陣圖。這個點陣圖的像素是16px 16px,或者是16px 16px的倍數。 每個圖標都放在單個行中彼此相鄰的點陣圖上。使用Alph ...
  • 最近有接觸到關於visual studio 2017 擴展的開發,特此記錄,也是為了督促自己去深入瞭解其原理。 開始開發Visual Studio 擴展,在這裡我安裝了visual studio 2017, 在安裝的時候記得勾選上visual studio 擴展開發。 創建一個項目 我們打開編譯器, ...
  • 由於數據類型多,要按照逐個類型寫一個類型轉換的方法的話一是代碼量多,顯得累贅。 ...
  • 電商平臺 都會有搶購的情況,比如 1元搶購。 而搶購 最重要的 就是庫存,很多情況下 庫存處理不好,就會出現超賣現象。 本文將用redis為緩存,StackExchange 框架,消息隊列方式 實現分散式鎖的情況 一,效果 先看效果, 窗體下單 構建高併發情況 開多個控制台應用程式 處理訂單 二,配 ...
  • 在asp.net中常見的<%%>方式有如下幾種: <%%>、<%=%>、<%:%>、<%#%>、<%$%>、<%@%> <%%>:書寫後臺代碼,如C#、vb等代碼 <%=%>:計算=後面的表達式,並將結果輸出 <%:%>:將:號後面的內容編碼輸出,實際<%=Server.HtmlEncode()%> ...
  • 一、C#語言 C#是微軟在2000開始推出的一種面向對象的編程語言。 它簡單易學、類型安全,可以用非常簡潔易懂的代碼寫出理想的功能,大大提高了開發人員的工作效率,並降低了程式的維護成本。 作為一種面向對象的語言,C#支持封裝、繼承和多態等概念。 按照微軟一貫的語法糖作風,在C#後續的版本里,陸續推出 ...
  • 編碼 ASCII--0~127 65-A 97-a 西歐碼表 ISO-8859-1 0-255 1個位元組 gb2312 0-65535 gbk 2個位元組 Unicode編碼體系 utf-8 3個位元組 中 f bit位 Byte位元組 1Byte = 8bit 1KB=1024B MB GB TB PB ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...