64位 unsigned char_Java位运算符详解
前言
之前了解過位運算符,左移<<等于乘以2,右移>>等于除以2。但是我在看jdk源碼的時候發現了一個>>>三個符號的,不明白這是什么意思,就去搜了一下,發現還挺多的知識點的,就整理了一下。
首先我們知道,我們編寫的程序最終都是在計算機底層進行的,計算機底層也僅支持0、1兩種符號。所以當時網上有個鍵盤只有0、1兩個鍵,那才是大佬用的鍵盤。扯遠了。。。
先來復習一下java的基本類型都占多少字節,占多少位(1字節等于8位):
類型
字節數
位數
大小范圍
byte
1
8
-2^8^~2^8^-1
short
2
16
-2^16^~2^16^-1
int
4
32
-2^32^~2^32^-1
long
8
64
-2^64^~2^64^-1
float
4
double
8
char
2
16
一個char類型可以存儲一個漢字
boolean
1
true or false
移位操作是把數據看作二進制數,然后將其向左或向右移動若干位的運算。在Java中,移位操作符包含三種:<<左移運算符,>>帶符號右移運算符,>>>無符號右移運算符。這三種操作符都只能作用于long,int,short,byte這四種基本整形類型上和char類型上。其他類型如double都無法使用位運算符,大家可以在ide中自行試驗一下。
在java中,第一位用來表示數字的正負,第一位為零時表示正數,第一位為1時表示負數。我們拿最簡單的8位byte類型舉例:0000 0000表示0,0111 1111這個表示最大值(2^8^-1),再進行加一后就變成了1000 0000這時就變成了最小值(-2^8^)。再加一后變成1000 0001這時的值為-127。也就是從0到最大值然后轉為最小值,然后再從最小值向零靠近。
左移操作符<<
左移操作符<<是將數據轉換為二進制后,向左移動若干位,高位丟棄,低位補零。
首先我們可以利用java中的方法獲取一個數的二進制:Integer.toBinaryString(int val)。
然后我們看下面這個例子:
public static void main(String[] args) {int a = 10;System.out.println("左移前的二進制:"+Integer.toBinaryString(a));a <<= 2;System.out.println("左移后的二進制:"+Integer.toBinaryString(a));System.out.println("左移后的十進制:"+a); }首先定義一個數,值為10,打印它的二進制(1010),然后進行左移操作2位。打印移位后的結果和二進制。
左移前的二進制:1010 左移后的二進制:101000 左移后的十進制:40可以看出,將原來的二進制向左移動了兩位,后面進行了補零。40=10 2 2。所以一次左移等于將這個數擴大了兩倍。再來看一個負數的左移:
int b = -8; System.out.println("左移前的二進制:" + Integer.toBinaryString(b)); b <<= 2; System.out.println("左移后的二進制:" + Integer.toBinaryString(b)); System.out.println("左移后的十進制:" + b);我們定義了一個負數(-8),打印出它的二進制,進行左移2位,左移后打印它的二進制,再將10進制打印出來查看。
左移前的二進制:11111111111111111111111111111000 左移后的二進制:11111111111111111111111111100000 左移后的十進制:-32可以明顯的看出二進制向左移動了兩位,前面的位置丟棄,后面的位置補零。轉換為10進制也符合我們之前的運算:-32 = -8 2 2。
帶符號右移操作符>>
剛才的左移中,它向左移動,高位進行了丟棄,低位進行補零。但是右移操作時有一個符號位,操作不當將造成答案與預期結果不同。
帶符號右移就是在向右移動若干位,低位進行丟棄,高位按照符號位進行填補。對于正數做右移操作時,高位補充0;負數進行右移時,高位補充1。
再來用例子證明一下:
public static void main(String[] args) {int a = 1024;System.out.println("a右移前的二進制:" + Integer.toBinaryString(a));a >>= 4;System.out.println("a右移后的二進制:" + Integer.toBinaryString(a));System.out.println("a右移后的十進制:"+a);int b = -70336;System.out.println("b右移前的二進制:" + Integer.toBinaryString(b));b >>= 4;System.out.println("b右移后的二進制:" + Integer.toBinaryString(b));System.out.println("b右移后的十進制:"+b); }定義了兩個變量,a=1024,然后向右移動4位。b=-70336也向右移動4位。分別將它們的移動前后二進制和十進制打印出來查看。
a右移前的二進制:10000000000 a右移后的二進制:1000000 a右移后的十進制:64 b右移前的二進制:11111111111111101110110101000000 b右移后的二進制:11111111111111111110111011010100 b右移后的十進制:-4396a原來的二進制向右移動后,低位被丟棄,高位補充符號位也就是0。b原來的二進制向右移動后,低位被丟棄,高位補充符號位1。這也符號我們之前的運算規律:1024 / 2^4^ =16 ;-70336/ 2^4^ = -4396。
無符號右移操作符>>>
剛才的帶符號右移操作符,我們在向右移動時帶著高位的符號,正數填充0,負數填充0。現在不帶符號的右移操作符大體與右移操作符一致,只不過不再區分正負數,結果都是高位補零,低位丟棄。
再用例子來證明一下:
public static void main(String[] args) {int a = 1024;System.out.println("a右移前的二進制:" + Integer.toBinaryString(a));a >>>= 4;System.out.println("a右移后的二進制:" + Integer.toBinaryString(a));System.out.println("a右移后的十進制:"+a);int b = -70336;System.out.println("b右移前的二進制:" + Integer.toBinaryString(b));b >>>= 4;System.out.println("b右移后的二進制:" + Integer.toBinaryString(b));System.out.println("b右移后的十進制:"+b); }還是剛才帶符號右移的例子:這次我們僅僅把操作符換成無符號的右移操作符。
按照定義,其實在正數時不會有變化,因為在帶符號的右移中正數也是高位補零。只不過當值為負數時會有變化,讓我們看一下輸出是不是符合猜想。
a右移前的二進制:10000000000 a右移后的二進制:1000000 a右移后的十進制:64 b右移前的二進制:11111111111111101110110101000000 b右移后的二進制:1111111111111110111011010100 b右移后的十進制:268431060確實正數沒有變化,驗證了我們的猜想。然后是負數,這次向右移動時高位進行了補零,低位丟棄。改變后的數值不再符合我們之前的規律。
在無符號右移中,當值為正數時,依然符合之前的規律移動一位相當于除以2。但是當值為負數時不再符合規律。
當移位的位數超過數值所占用的位數會怎么樣?
這個問題很有意思,我們剛剛都僅僅移動了2位或者4位,如果我們超過了int的位數也就是32位后會怎么樣?我們如果對一個正數左移32位,低位補零補充了32次就變成0了,就如同下面代碼所寫的一樣,最終a的結果會是什么。會變成0嗎?
public static void main(String[] args) {int a = 10;a <<= 32;System.out.println(a); }經過我們運行后發現a的結果最終沒變還是10。我們如果改成左移33位,它的結果會變成20。那么它的運算規律會不會是當超過位數后僅僅移動對位數的余數呢?比如對int做操作,它實際是運算 位數%32次。
經過多次試驗發現答案確實就是這個猜想,當對int類型處理時,右移x位的運算為x%32位。
對其他類型也是一樣嗎?
我們剛才都是用的int類型,那么對于byte,short,char,long都一樣嗎?
先看一下byte類型。
public static void main(String[] args) {byte b = -1;System.out.println("操作前:"+b);b >>>= 6;System.out.println("操作后:"+b); }定義了byte的值為-1,即1111 1111,然后無符號右移6位,高位補零,低位丟棄,那么應該變成0000 0011也就是是3。讓我們運行一下這段代碼看一下打印出來的信息是不是3呢?
操作前:-1 操作后:-1運行結果與我們預期的結果不一致!
我們將它的二進制也一起打印出來看一下究竟:
public static void main(String[] args) {byte b = -1;System.out.println("操作前十進制:"+b);System.out.println("操作前二進制:"+Integer.toBinaryString(b));b >>>= 6;System.out.println("操作后二進制:"+Integer.toBinaryString(b));System.out.println("操作后十進制:"+b); }這時再看一下運行結果
操作前十進制:-1 操作前二進制:11111111111111111111111111111111 操作后二進制:11111111111111111111111111111111 操作后十進制:-1原來,Java在對byte,short,char這三種類型進行移位操作前,會將其先轉型為int類型,然后再進行位操作。由于我們有進行了重新賦值將其賦值為原來的byte類型,所以又進行了從int到byte的先下轉型,也就是截斷。我們對上面的例子進行一下修改可以更直觀的發現運行過程:
public static void main(String[] args) {byte b = -1;System.out.println("操作前十進制:"+b);System.out.println("操作前二進制:"+Integer.toBinaryString(b));System.out.println("進行無符號右移6位后的十進制:"+(b>>>6));System.out.println("操作后二進制:"+Integer.toBinaryString(b>>>6)); }在這里我沒有使用=進行重新賦值,而是計算完成后直接打印十進制和二進制的結果。
操作前十進制:-1 操作前二進制:11111111111111111111111111111111 進行無符號右移6位后的十進制:67108863 操作后二進制:11111111111111111111111111從打印結果中可以明顯的看出是先轉換為int類型,然后進行位運算,位運算結束后由于重新賦值所以進行的截斷。
對于long類型,它是64位,不用先轉換。
總結
移位符是Java中的基本操作符,實際支持的類型只有int和long。在對byte,short,char類型進行移位操作時,都會先將其轉換為int類型再進行操作。左移<<操作符相當于乘以2。帶符號右移操作符>>相當于除以2。在Java中使用位運算符會比乘*,除/運算符更高效一些。而無符號右移符>>>在移動時高位補零,低位丟棄,在正數時仍然相當于除以2,但是在負數時結果卻是變大了(由負數變為正數)。
本文由博客一文多發平臺 OpenWrite 發布!博主郵箱:liunaijie1996@163.com,有問題可以郵箱交流。
總結
以上是生活随笔為你收集整理的64位 unsigned char_Java位运算符详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: cmw500综合测试仪使用_综合布线中手
- 下一篇: 网页游戏怎么修改数据_一周网页游戏数据报