Java基礎(chǔ)教程之整數(shù)運(yùn)算
引言
Java的整數(shù)運(yùn)算遵循四則運(yùn)算規(guī)則,可以使用任意嵌套的小括號(hào)。四則運(yùn)算規(guī)則和初等數(shù)學(xué)一致。例如:
public class Main { public static void main(String[] args) { int i=(100+200)*(99-88);//3300 int n=7*(5+(i-9));//23072 System.out.println(i); System.out.println(n); } }
輸出
3300
23072
整數(shù)運(yùn)算的數(shù)值不但是精確的,而且整數(shù)運(yùn)算永遠(yuǎn)是精確的,即使是出發(fā),因?yàn)閮蓚€(gè)整數(shù)相除只得到結(jié)果的整數(shù)部分,不進(jìn)行四舍五入
int x=11/3;
求余運(yùn)算
int x=11%3;
整數(shù)除法對(duì)于被除數(shù)為0運(yùn)行時(shí)報(bào)錯(cuò),但編譯時(shí)不報(bào)錯(cuò)
溢出
整數(shù)由于存在范圍限制,如果計(jì)算結(jié)果超出了范圍,就會(huì)產(chǎn)生溢出,而溢出不會(huì)報(bào)錯(cuò)而會(huì)得到一個(gè)奇怪的結(jié)果。
public class Main { public static void main(String[] args) { int x=2147483640; int y=15; int sum=x+y; System.out.println(sum); } }
運(yùn)行結(jié)果
-2147483641
要解釋上述結(jié)果,我們把整數(shù)2147483640和15換成二進(jìn)制做加法
0111 1111 1111 1111 1111 1111 1111 1000
+ 0000 0000 0000 0000 0000 0000 0000 1111
1000 0000 0000 0000 0000 0000 0000 0111
由于最高位計(jì)算結(jié)果為1,因此加法結(jié)果變成了一個(gè)負(fù)數(shù)
要解決上面的文件,可以把int換成long類型,由于long可表示的整型范圍更大,所以結(jié)果不會(huì)溢出
public class Main { public static void main(String[] args) { long x=2147483640; long y=15; long sum=x+y; System.out.println(sum); } }
還有一種簡寫的運(yùn)算符,即+=,-=,*=,/=,使用方法如下
n+=100; //相當(dāng)于n=n+100 n-=100;//相當(dāng)于n=n-100
自增/自減
Java還提供了++運(yùn)算和--運(yùn)算,它們可以對(duì)一個(gè)整數(shù)進(jìn)行加1和減1的操作:
public class Main { public static void main(String[] args) { int n=100; n++; System.out.println(n); n--; System.out.println(n); } }
注意++寫在前面和后面計(jì)算結(jié)果是不同的,++n表示先加1再引用n,n++表示先引用n再加1。不建議把++運(yùn)算混入到常規(guī)運(yùn)算中,容易自己把自己搞懵了。
移位運(yùn)算
在計(jì)算機(jī)中,整數(shù)總是以二進(jìn)制的形式表示。例如,int類型的整數(shù)7使用4字節(jié)表示的二進(jìn)制如下:
00000000 00000000 00000000 00000111
可以對(duì)整數(shù)進(jìn)行移位運(yùn)算。對(duì)整數(shù)7左移1位將得到整數(shù)14,左移2位將得到整數(shù)28
int n = 7; // 00000000 00000000 00000000 00000111 = 7 int a = n << 1; // 00000000 00000000 00000000 00001110 = 14 int b = n << 2; // 00000000 00000000 00000000 00011100 = 28 int c = n << 28; // 01110000 00000000 00000000 00000000 = 1879048192 int d = n << 29; // 11100000 00000000 00000000 00000000 = -536870912
左移29位時(shí),由于最高位變成了1,因此結(jié)果變成了負(fù)數(shù)
類似地對(duì)證書7進(jìn)行右移結(jié)果如下
int n = 7; // 00000000 00000000 00000000 00000111 = 7 int a = n >> 1; // 00000000 00000000 00000000 00000011 = 3 int b = n >> 2; // 00000000 00000000 00000000 00000001 = 1 int c = n >> 3; // 00000000 00000000 00000000 00000000 = 0
如果對(duì)一個(gè)負(fù)數(shù)進(jìn)行右移,最高位1不動(dòng),結(jié)果仍然是一個(gè)負(fù)數(shù)
int n = -536870912; int a = n >> 1; // 11110000 00000000 00000000 00000000 = -268435456 int b = n >> 2; // 10111000 00000000 00000000 00000000 = -134217728 int c = n >> 28; // 11111111 11111111 11111111 11111110 = -2
還有一種不帶符號(hào)的右移運(yùn)算,使用>>>,它的特點(diǎn)是符號(hào)位跟著動(dòng),因此,對(duì)一個(gè)負(fù)數(shù)進(jìn)行>>>右移,它會(huì)變成正數(shù),原因是最高位的1變成了0:
int n = -536870912; int a = n >>> 1; // 01110000 00000000 00000000 00000000 = 1879048192 int b = n >>> 2; // 00111000 00000000 00000000 00000000 = 939524096 int c = n >>> 29; // 00000000 00000000 00000000 00000111 = 7 int d = n >>> 31; // 00000000 00000000 00000000 00000001 = 1
對(duì)byte和short類型進(jìn)行位移時(shí),會(huì)首先轉(zhuǎn)換為int再進(jìn)行位移
左移實(shí)際上就是不斷地*2,右移實(shí)際上就是不斷地/2
位運(yùn)算
位運(yùn)算是按位進(jìn)行與,或,非和異或的運(yùn)算。
與運(yùn)算的規(guī)則是,必須兩個(gè)數(shù)同時(shí)為1,結(jié)果才為1
n=0 & 0;//0 n=0 & 1;//0 n=1 & 0;//0 n=1 & 1;//1
或運(yùn)算的規(guī)則是,只要任意一個(gè)為1,結(jié)果就為1
n = 0 | 0; // 0 n = 0 | 1; // 1 n = 1 | 0; // 1 n = 1 | 1; // 1
非運(yùn)算的規(guī)則是,0和1呼喚
n = ~0; // 1 n = ~1; // 0
異或運(yùn)算的規(guī)則是,如果兩個(gè)數(shù)不同,結(jié)果為1,否則為0
n = 0 ^ 0; // 0 n = 0 ^ 1; // 1 n = 1 ^ 0; // 1 n = 1 ^ 1; // 0
對(duì)于兩個(gè)整數(shù)的運(yùn)算,實(shí)際上就是按位對(duì)齊,然后依次對(duì)每一位進(jìn)行運(yùn)算。例如
public class Main { public static void main(String[] args) { int i = 167776589; int n = 167776512; System.out.println(i&n); } }
運(yùn)行結(jié)果
167776512
上述按位與運(yùn)算實(shí)際上可以看作兩個(gè)整數(shù)表示的IP地址10.0.17.77
和10.0.17.0
,通過與運(yùn)算,可以快速判斷一個(gè)IP是否在給定的網(wǎng)段內(nèi)。
運(yùn)算優(yōu)先級(jí)
在Java的計(jì)算表達(dá)式中,運(yùn)算優(yōu)先級(jí)從高到低依次是:
- ()
- ! ~ ++ --
- * / %
- + -
- << >> >>>
- &
- |
- += -= *= /=
記不住也沒關(guān)系,只需要加括號(hào)就可以保證運(yùn)算的優(yōu)先級(jí)正確。
類型的自動(dòng)提升與強(qiáng)制轉(zhuǎn)型
在運(yùn)算過程中,如果參與運(yùn)算的兩個(gè)數(shù)類型不一致,那么計(jì)算結(jié)果為較大類型的整型。例如,short和int計(jì)算,結(jié)果總是int,原因是short首先自動(dòng)被轉(zhuǎn)型為int:
public class Main { public static void main(String[] args) { short s = 1234; int i = 123456; int x = s + i; //s自動(dòng)轉(zhuǎn)換為int short y = s + i;//編譯錯(cuò)誤 } }
也可以將結(jié)果強(qiáng)制轉(zhuǎn)型,即將大范圍的整數(shù)轉(zhuǎn)型為小范圍的整數(shù)。強(qiáng)制轉(zhuǎn)型使用(類型),例如,將int強(qiáng)制轉(zhuǎn)型為short:
int i=12345; short s = (short) i;//12345
超出范圍的強(qiáng)制轉(zhuǎn)型會(huì)得到錯(cuò)誤的結(jié)果,原因是轉(zhuǎn)型時(shí),int的兩個(gè)高位直接直接被扔掉,僅保留了低位的兩個(gè)字節(jié)。
舉例說明
public class Main { public static void main(String[] args) { int i1 = 1234567; short s1 = (short) i1; // -10617 System.out.println(s1); int i2 = 12345678; short s2 = (short) i2; // 24910 System.out.println(s2); } }
結(jié)果
-10617
24910
為什么結(jié)果是-10617和24910呢
首先把1234567轉(zhuǎn)換成二進(jìn)制并且使用8位分割成4份
00000000 00010010 11010110 10000111?
強(qiáng)制轉(zhuǎn)換成short類型或高位被拋棄留下低位兩個(gè)字節(jié)
11010110 10000111
最高位為1是負(fù)數(shù),負(fù)數(shù)是以補(bǔ)碼的形式存儲(chǔ)在計(jì)算機(jī)內(nèi)需要轉(zhuǎn)換成原碼
原碼等于補(bǔ)碼-1后除符號(hào)位取反
補(bǔ)碼-1結(jié)果
11010110 10000110
除符號(hào)位取反得到原碼
10101001 01111001
最高位為1所以是負(fù)數(shù)101001 01111001即-10617
同理計(jì)算12345678去掉高兩位后剩下的最高位為0是正數(shù)則補(bǔ)碼和原碼是一樣的
練習(xí)
計(jì)算自然數(shù)之和
public class Main { public static void main(String[] args) { int n=100; int sum=0; for(int i=1;i<=n;i++) { sum=sum+i; } System.out.println(sum); } }
小結(jié)
整數(shù)運(yùn)算的結(jié)果永遠(yuǎn)都是精確的
運(yùn)算結(jié)果會(huì)自動(dòng)提升
可以強(qiáng)制轉(zhuǎn)型,但超出范圍的強(qiáng)制轉(zhuǎn)型會(huì)得到錯(cuò)誤的結(jié)果
應(yīng)該選擇合適范圍的整型(int或long),沒有必要為了節(jié)省內(nèi)存而使用byte和short進(jìn)行整數(shù)運(yùn)算。
總結(jié)
到此這篇關(guān)于Java基礎(chǔ)教程之整數(shù)運(yùn)算的文章就介紹到這了,更多相關(guān)Java整數(shù)運(yùn)算內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
zuul集成Sentinel,完成對(duì)path映射的限流操作
這篇文章主要介紹了zuul集成Sentinel,完成對(duì)path映射的限流操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06Spring Boot 項(xiàng)目做性能監(jiān)控的操作流程
這篇文章主要介紹了Spring Boot 項(xiàng)目如何做性能監(jiān)控,本文通過實(shí)例代碼圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07mybatis攔截器實(shí)現(xiàn)通用權(quán)限字段添加的方法
這篇文章主要給大家介紹了關(guān)于mybatis攔截器實(shí)現(xiàn)通用權(quán)限字段添加的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用mybatis具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09使用java文件過濾器輸出制定格式文件路徑的實(shí)例代碼
這篇文章主要介紹了使用java文件過濾器輸出制定格式文件路徑的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-11-11Spring 開發(fā)之組件賦值的實(shí)現(xiàn)方法
這篇文章主要介紹了Spring 開發(fā)之組件賦值的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09一次Spring無法啟動(dòng)的問題排查實(shí)戰(zhàn)之字節(jié)碼篇
最近學(xué)習(xí)了spring相關(guān)知識(shí),公司項(xiàng)目也用到了spring,下面這篇文章主要給大家介紹了一次Spring無法啟動(dòng)的問題排查實(shí)戰(zhàn)之字節(jié)碼篇的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-04-04